Javamail SMTP properties protocol name confusion - email

I cannot understand what I'm missing in Javamail configuration. I'm a bit confused about "protocol" part of properties key.
This is my SMTP code:
public Session getSendSession(){
Properties props = new Properties();
String protocol="smtps";
props.put("mail.host", "smtp.myserver.com");
props.put("mail.transport.protocol", protocol);
props.put("mail."+protocol+".port", 587);
if(protocol!=null && protocol.toLowerCase().endsWith("s")){
props.put("mail."+protocol+".ssl.enable","true");
try {
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
props.put("mail."+protocol+".ssl.socketFactory", sf);
} catch (GeneralSecurityException e) {
throw new SystemException(e);
}
props.put("mail."+protocol+".ssl.trust","*");
}
props.put("mail."+protocol+".auth", "true");
Session mailSession= Session.getInstance(props,
new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("test#myserver.com","test");
}
});
mailSession.setDebug(true);
return mailSession;
}
This is the debug output of Props:
{mail.smtps.ssl.enable=true, mail.transport.protocol=smtps, mail.smtps.port=587, mail.smtps.ssl.trust=*, mail.smtps.auth=true, mail.host=smtp.myserver.com, mail.smtps.ssl.socketFactory=com.sun.mail.util.MailSSLSocketFactory#cfa4b2}
With this configuration I got this debug output:
DEBUG: setDebug: JavaMail version 1.4.7
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]
DEBUG SMTP: useEhlo true, useAuth false
DEBUG SMTP: trying to connect to host "smtp.myserver.com", port 25, isSSL false
As you see the ssl and port configuration is ignored!
If I change the protocol part of each properties with simply "smtp" (without "s") the connection success:
public Session getSendSession(){
Properties props = new Properties();
String protocol="smtps";
props.put("mail.host", "smtp.myserver.com");
props.put("mail.transport.protocol", protocol);
props.put("mail.smtp.port", 587);
if(protocol!=null && protocol.toLowerCase().endsWith("s")){
props.put("mail.smtp.ssl.enable","true");
try {
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
props.put("mail.smtp.ssl.socketFactory", sf);
} catch (GeneralSecurityException e) {
throw new SystemException(e);
}
props.put("mail.smtp.ssl.trust","*");
}
props.put("mail.smtp.auth", "true");
Session mailSession= Session.getInstance(props,
new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("test#myserver.com","test");
}
});
mailSession.setDebug(true);
return mailSession;
}
Props debug:
{mail.smtp.port=587, mail.smtp.ssl.trust=*, mail.transport.protocol=smtps, mail.smtp.auth=true, mail.smtp.ssl.enable=true, mail.host=smtp.myserver.com, mail.smtp.ssl.socketFactory=com.sun.mail.util.MailSSLSocketFactory#45760}
Debug output:
DEBUG: setDebug: JavaMail version 1.4.7
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]
DEBUG SMTP: useEhlo true, useAuth true
DEBUG SMTP: useEhlo true, useAuth true
DEBUG SMTP: trying to connect to host "smtp.myserver.com", port 587, isSSL true
I also looked into javamail source and seems that the properties is read with the "mail."+(protocol/name)+".value" as expected.
What I'm missing?
What I'm missing?

The property names need to match the protocol name you pass to Session.getTransport or Session.getStore. As you discovered, Transport.send chooses the protocol based on the address types used in the message (almost always "rfc822", and thus the "smtp" protocol). You can change the mapping from address type to protocol if you need to, but the simpler approach is to just set properties for the "smtp" protocol. And you don't need to use MailSSLSocketFactory if you're setting the mail.smtp.ssl.trust property.
Also, you're using a very old version of JavaMail. The current version is 1.6.2, please upgrade if possible.

Related

in java: when I fetch imaps folders multiple in one minute, i see this error: Unexpected item LIST

my code is
import javax.mail.Folder;
import javax.mail.Session;
import javax.mail.Store;
import javax.net.ssl.SSLContext;
import java.util.Properties;
....
....
Store store = null;
Folder mailFolder = null;
Properties props = System.getProperties();
props.setProperty("mail.store.protocol", "imaps");
try {
SSLContext ctx = SSLContext.getInstance("TLSv1.2");
ctx.init(null, null, null);
SSLContext.setDefault(ctx);
} catch (Exception e) {
e.printStackTrace();
}
props.setProperty("mail.imaps.sasl.enable", "true");
Session session2 = Session.getDefaultInstance(props);
session2.setDebug(true);
store = session2.getStore("imaps");
store.connect("mailtest.com", 993, "test", "test");
mailFolder = store.getDefaultFolder();
javax.mail.Folder[] f = mailFolder.list("*");
debug is:
DEBUG: setDebug: JavaMail version 1.4ea DEBUG: getProvider()
returning
javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Sun
Microsystems, Inc] DEBUG: mail.imap.fetchsize: 16384 DEBUG: enable
SASL
OK mailtest.com A0 CAPABILITY
CAPABILITY IMAP4rev1 CHILDREN IDLE LITERAL+ MULTIAPPEND SPECIAL-USE NAMESPACE UIDPLUS QUOTA XLIST ID LOGINDISABLED AUTH=CRAM-MD5
AUTH=DIGEST-MD5 AUTH=GSSAPI ACL RIGHTS=texkbn A0 OK CAPABILITY
completed IMAP DEBUG: AUTH: CRAM-MD5 IMAP DEBUG: AUTH: DIGEST-MD5
IMAP DEBUG: AUTH: GSSAPI DEBUG: protocolConnect login,
host=mailtest.com, user=test, password= IMAP SASL DEBUG:
Mechanisms: CRAM-MD5 DIGEST-MD5 GSSAPI IMAP SASL DEBUG: callback
length: 2 IMAP SASL DEBUG: callback 0:
javax.security.auth.callback.NameCallback#663b1c53 IMAP SASL DEBUG:
callback 1: javax.security.auth.callback.PasswordCallback#32c0c194
IMAP SASL DEBUG: SASL client CRAM-MD5 A1 AUTHENTICATE CRAM-MD5
PDQwMjM2ODc1MTEuMTU2NjkxNDZAd2VibWFpbC5zaGlyYXp1LmFjLmlyPg== IMAP SASL DEBUG: challenge: 4023687511.15669146#mailtest.com : IMAP SASL
DEBUG: response: test 8127c2303f4866ee9e7e934227f10bc7 :
c3NvdGVzdDEgODEyN2MyMzAzZjQ4NjZlZTllN2U5MzQyMjdmMTBiYzc= A2 LIST ""
"*" A1 NO AUTHENTICATE failed A2 BAD Error: Unexpected item LIST
javax.mail.MessagingException: A2 BAD Error: Unexpected item LIST;
nested exception is:
com.sun.mail.iap.BadCommandException: A2 BAD Error: Unexpected item LIST
at com.sun.mail.imap.IMAPFolder.doCommand(IMAPFolder.java:2337)
at com.sun.mail.imap.DefaultFolder.list(DefaultFolder.java:62)
at com.liferay.portlet.action.NotificationPortlet.serveResource(NotificationPortlet.java:146)
The key:
A1 NO AUTHENTICATE failed
A2 BAD Error: Unexpected item LIST
The first line says you couldn't log in, for whatever reason. Because of that, the next command surprised the server. (The LIST command is only valid after successful login.)

Unable to send more than 5 emails to Exchange server using JavaMail

I have a method that sends many emails to exchange server over smtp using JavaMail, below is my code,
public void sendMail(){
final String host="host",port="587",username="mail1#local.local",password="password",from="";
try {
Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.host", host);
props.put("mail.smtp.port", port);
props.put("mail.smtp.ssl.trust", host);
final String email = from;
Authenticator authenticator = new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
};
Session session = Session.getInstance(props,authenticator);
InternetAddress replyToAddress [] = new InternetAddress[1];
replyToAddress[0] = new InternetAddress("mail1#local.local");
Transport transport = session.getTransport("smtp");
MimeMessage mimeMessage = new MimeMessage(session);
mimeMessage.setFrom(new InternetAddress("mail1#local.local"));
mimeMessage.addRecipient(Message.RecipientType.TO, new InternetAddress("mail2#local.local"));
mimeMessage.setSubject("Test");
mimeMessage.setText("Hello Testing");
mimeMessage.setReplyTo(replyToAddress);
transport.send(mimeMessage);
System.out.println("Email has been Sent Successfully to");
} catch (MessagingException e) {
e.printStackTrace();
}
Now when I apply a loop and call this function 10 times then only first five emails are sent successfully, for rest of the request I get the following exception,
javax.mail.MessagingException: Can't send command to SMTP host;
nested exception is:
java.net.SocketException: Connection closed by remote host
at com.sun.mail.smtp.SMTPTransport.sendCommand(SMTPTransport.java:2157)
at com.sun.mail.smtp.SMTPTransport.sendCommand(SMTPTransport.java:2144)
at com.sun.mail.smtp.SMTPTransport.close(SMTPTransport.java:1210)
at javax.mail.Transport.send0(Transport.java:197)
at javax.mail.Transport.send(Transport.java:124)
if I increase the request count then still only first five emails are sent, rest of them throws the exception.
If I put the failed request in some queue and retry them later then some of them will be sent.
Any clue will be appreciated, do I need to check for some configuration on Exchange server?
We have seen this exact same issue with a MS Exchange Server 2010. We had to increase the ReceiveConnector message rate limit by issuing the following Powershell-command:
Set-ReceiveConnector "Client CLIENTNAME" -MessageRateLimit unlimited

Getting the JavaMail API to Work... Again

I'm working on an application that uses the JavaMail API to send an email, but I keep getting errors. I'm using Eclipse to code it and I'm using gmail to send it. I took out my real password for obvious reasons so you're probably going to need to replace that with your own if you need to experiment. Now that I've fixed some stuff thanks to you guys, I think I'm getting a timeout error because it takes a long time until it displays the error, but beyond that much, I haven't the foggiest clue. Thanks in advance for any help or advice once more.
Code:
package com.brighamcampbell.sunrisegundersonmail;
import java.io.UnsupportedEncodingException;
import java.util.Properties;
import javax.mail.*;
import javax.mail.internet.*;
public class Mail {
public static void main(String[] args) throws MessagingException,
UnsupportedEncodingException {
Properties mailProps = new Properties();
mailProps.put("mail.smtp.from", "butterscotchdreamer23#gmail.com");
mailProps.put("mail.smtp.host", "smtp.gmail.com");
mailProps.put("mail.smtp.ssl.trust", "smtp.gmail.com");
mailProps.put("mail.smtp.port", "465");
mailProps.put("mail.smtp.auth", true);
mailProps.put("mail.smtp.starttls.enable", "true");
Session mailSession = Session.getDefaultInstance(mailProps, new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("butterscotchdreamer23#gmail.com", "password");
}
});
MimeMessage message = new MimeMessage(mailSession);
//set the email sender
message.setFrom(new InternetAddress("butterscotchdreamer23#gmail.com"));
//set the email recipients
String[] emails = { "butterscotchdreamer23#gmail.com" };
InternetAddress dests[] = new InternetAddress[emails.length];
for (int i = 0; i < emails.length; i++) {
dests[i] = new InternetAddress(emails[i].trim().toLowerCase());
}
message.setRecipients(Message.RecipientType.TO, dests);
//set the email subject
message.setSubject("test");
//set the email content
message.setText("this is a test");
//send
System.out.println("sending...");
Transport.send(message);
System.out.println("done sending email!");
}
}
Error:
Exception in thread "main" javax.mail.MessagingException: Could not connect to SMTP host: smtp.gmail.com, port: 465, response: -1
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:2041)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:697)
at javax.mail.Service.connect(Service.java:386)
at javax.mail.Service.connect(Service.java:245)
at javax.mail.Service.connect(Service.java:194)
at javax.mail.Transport.send0(Transport.java:253)
at javax.mail.Transport.send(Transport.java:124)
at com.brighamcampbell.sunrisegundersonmail.Mail.main(Mail.java:56)
Thanks for the patience!
Clearly the mail server doesn't support STARTTLS, so you shouldn't enable it.
Try removing the 3 sslfactory properties as it is not needed anymore for javamail.You should be able to connect that way.
Note:The gmail server definitely support STARTTLS:
x#test:~/$ telnet smtp.gmail.com 587
Trying 74.125.136.108...
Connected to gmail-smtp-msa.l.google.com.
Escape character is '^]'.
220 mx.google.com ESMTP vv9sm12826892wjc.35 - gsmtp
EHLO me
250-mx.google.com at your service, [147.58.51.121]
250-SIZE 35882577
250-8BITMIME
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-PIPELINING
250-CHUNKING
250 SMTPUTF8
QUIT
General Gmail instructions are here, general connection debugging tips are here, and a list of common mistakes is here. Possibly you're running into a firewall or anti-virus program that's intercepting your attempt to connect. If you still can't make it work, post the JavaMail debug output.

Error while connecting to openfire server using asmack 4.0.2

Im trying to connect to Openfire Server using Asmack library 4.0.2.Im failing to get connected to the server even though i had provided correct ip address with the port.
public static final String HOST = "192.168.1.100";
public static final int PORT = 9090;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
connect();
}
public void connect(){
AsyncTask<Void, Void, Boolean> connectionThread = new AsyncTask<Void, Void, Boolean>(){
#Override
protected Boolean doInBackground(Void... arg0){
boolean isConnected = false;
ConnectionConfiguration config = new ConnectionConfiguration(HOST,PORT);
config.setReconnectionAllowed(true);
config.setSecurityMode(SecurityMode.disabled);
config.setDebuggerEnabled(true);
XMPPConnection connection = new XMPPTCPConnection(config);
try{
connection.connect();
Log.i("XMPPChatDemoActivity","Connected to " + connection.getHost());
isConnected = true;
} catch (IOException e){
Log.e("XMPPIOExceptionj", e.toString());
} catch (SmackException e){
Log.e("XMPPSmackException", e.toString()+" Host:"+connection.getHost()+"Port:"+connection.getPort());
} catch (XMPPException e){
Log.e("XMPPChatDemoActivity", "Failed to connect to "
+ connection.getHost());
Log.e("XMPPChatDemoActivity", e.toString());
}
return isConnected;
}
};
connectionThread.execute();
}
And im getting the following error possibly because Host and Port are getting assigned null and 0 respectively even though i had assigned them correctly.Pls help me in
sorting out this connection prob.
08-12 22:10:20.496: E/XMPPSmackException(4341):org.jivesoftware.smack.SmackException$NoResponseException Host:nullPort:0
Can you confirm that port 9090 is the correct port for XMPP protocol? Default install of Openfire will set port 9090 to be used for accessing the HTTP based configuration console. I recommend you try connecting to the port for XMPP connections as specified on the main index page of the Openfire configuration console (Listed below "Server Ports").
The following is taken from the Openfire configuration console:
5222 The standard port for clients to connect to the server. Connections may or may not be encrypted. You can update the security settings for this port.
I think your Host adress is wrong too, you must use the adress to connect openfire server. It must be "127.0.0.1" or just write "localhost". and the port is 5222 to be able to talk from client to server.

Client cannot access server which bind loopback address in C#

Now a socket in server side binds 192.168.1.69:9000,and then start to listen. Client connects the server using 127.0.0.1:9000. But fail. However,it works when client connect the server using 192.168.1.69:9000. Client and server are both running on the same commputer.My question is: it should be successful When client using loopback address connect the server, but fail.Why?
Server Code:
this.pro_ListenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
this.pro_ListenSocket.ReceiveBufferSize = this.pro_BufferSize;
this.pro_ListenSocket.SendBufferSize = this.pro_BufferSize;
try
{
this.pro_ListenSocket.Bind(new IPEndPoint(this.pro_ServerIP, this.pro_Port));
}
catch (SocketException socketError)
{
return false;
}
catch (Exception)
{
return false;
}
try
{
this.pro_OnRunning = true;
this.pro_ListenSocket.Listen(500);
this.StartToAcceptClient(this.pro_ListenSocket);
}
catch (Exception ex)
{
return false;
}
Loopback is represented as a network adapter, just like any other. You have set your server to only listen for connections on the adapter at 192.168.1.69. If you want your server to listen on additional adapters, the easiest approach is to make it available on all available adapters by specifying the address IPAddress.Any (0.0.0.0).
this.pro_ListenSocket.Bind(new IPEndPoint(IPAddress.Any, this.pro_Port));