I use code from this link to access gmail imap server, because I could not find Android-friendly port of javamail with OAUTH support (javamail 1.5.2 or higher).
However, the problem with this code:
public static IMAPStore connectToImap(String host, int port, String userEmail, String oauthToken, boolean debug) throws Exception {
Properties props = new Properties();
props.put("mail.imaps.sasl.enable", "true");
props.put("mail.imaps.sasl.mechanisms", "XOAUTH2");
props.put(OAuth2SaslClientFactory.OAUTH_TOKEN_PROP, oauthToken);
Session session = Session.getInstance(props);
session.setDebug(debug);
final URLName unusedUrlName = null;
IMAPSSLStore store = new IMAPSSLStore(session, unusedUrlName);
final String emptyPassword = "";
store.connect(host, port, userEmail, emptyPassword);
return store;
}
is that a new Store object is created every time auth token is changed (expires). And then I have to create a new Folder and read my messages again...
My question is:
Is it possible to change auth token without creating a new Store object? I would like to be able to implement something like
store.connect("imap.gmail.com", username, oauth2_access_token)
(example from javamail 1.5.2) to reconnect, without the need to recreate the Store object.
Thank you very much!
If you need to create a new connection with the same Store you should be able to set the property to a new value and make a new connection, without creating a new Store object. Just call props.put with the new value. The Session keeps a reference to the Properties object rather than making a copy of it.
Related
My Java Windows app needs to send email and allow the user to specify his/her email account credentials: host, port, username, password. It works when I use my credentials for an account at my hosting service, but not so well when using a Gmail account, as my prospective users might want to do. The problem is Gmail insists on an "App password." So, I follow the Google instructions and create a 16-character App password which Google says has to be used one time only. However, I find that the App password MUST be used for subsequent runs.
Here's a sample program that demonstrates the problem. It will fail if I use that actual password for the Gmail account. It will work after I've created an App/device specific password (16 characters) and used it as the password, as it should. But, I have to use that 16-character password thereafter as well. What am I missing?
public class SendEmailTLS {
// Example 1 from https://www.mkyong.com/java/javamail-api-sending-email-via-gmail-smtp-example/
public static void main(String[] args) {
final String username = "me123#gmail.com";
final String password = "mypassword";
Properties prop = new Properties();
prop.put("mail.smtp.host", "smtp.gmail.com");
prop.put("mail.smtp.port", "587");
prop.put("mail.smtp.auth", "true");
prop.put("mail.smtp.starttls.enable", "true"); //TLS
Session session = Session.getInstance(prop,
new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
try {
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress("me123#gmail.com"));
message.setRecipients(
Message.RecipientType.TO,
InternetAddress.parse("you456#hotmail.com")
);
message.setSubject("Testing Gmail TLS");
message.setText("Dear sir,"
+ "\n\n I'm testing TLS,using port 587");
Transport.send(message);
System.out.println("Done");
} catch (MessagingException e) {
e.printStackTrace();
}
}
}
I want to add that I'm now suspecting that what I'm seeing is the way it's supposed to work. I had been thinking the 16-char App specific pw was a "Salt" kind of thing to protect the Gmail server. I have now read that it's really just an alternative password for my Gmail account. If anyone can confirm or deny this new perspective, I would be grateful.
I have a simple web application where different users can log into it. One of the important feature is user can access a document and send email of it's content to an outsider like third party. Below is just how the email looks like to give an idea:
It's pretty self explanatory and I can send to multiple user if I want like abc#example.com,efg#hotmail.com,... in the field box shown.With all this, I am using Java Mail API to make it work and after hitting the send button,it sends directly to the recipient.No issue at all.
Now, I want to modify this by doing this email feature as a service.What this means is when I send the email,the content and info filled in will be stored in a table in MYSQL and the service(running in background) will pick up from the table and do the sending.
This is my function:
public void sendEmail(String recipient, String subject, String content,
String host, String port, final String senderaddress,
final String password) {
try {
System.out.println("Please Wait, sending email...");
/*Setup mail server */
Properties props = new Properties();
props.put("mail.smtp.host", host); //SMTP Host
props.put("mail.smtp.port", port); //TLS Port
props.put("mail.smtp.auth", "true"); //enable authentication
props.put("mail.smtp.starttls.enable", "true"); //enable STARTTLS
//create Authenticator object to pass in Session.getInstance argument
Authenticator auth = new Authenticator() {
//override the getPasswordAuthentication method
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(senderaddress, password);
}
};
Session session = Session.getInstance(props, auth);
session.setDebug(true);
// Define message
MimeMessage message = new MimeMessage(session);
// Set From: header field of the header.
message.setFrom(new InternetAddress(senderaddress));
message.addRecipients(Message.RecipientType.TO,
InternetAddress.parse(recipient));
// Set Subject: header field
message.setSubject(subject);
// Now set the actual message
message.setText(content);
try {
Transport.send(message);
} catch (AddressException addressException) {
addressException.printStackTrace();
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
Can this be done in the way I want because I am unsure how to make it work?
1 ) After hitting Sending mail button from UI, You need to call a method for saving data like recipient, subject, content in DB
2)Write an email sender Service which retrieves non_delivered / pending mail from DB table and send it through Java Mail API
3)Scheduled email sender service with the help of ScheduledExecutorService
When I am trying to connect to an iCloud account using Javamail, it is returning an [AUTHENTICATION FAILED] error. This code worked for other non-OAuth providers as well (such as AOL, some Yahoo users). But, it is not working for iCloud.
Suggestions?
Properties props = new Properties();
props.put("mail.imaps.ssl.trust", "*");
Session session = Session.getInstance(props);
session.setDebug(true);
final URLName unusedUrlName = null;
IMAPSSLStore store = new IMAPSSLStore(session, unusedUrlName);
store.connect("imap.mail.me.com", 993, <userEmail>#icloud.com, <non-null-password>);
I want to create my DbxRequestConfig Object with a StandardHttpRequestor, because I need it to use a Proxy.
The Proxy is a http Proxy, Port 80, and needs authentication.
Proxyaddress: http://myproxy.com
Proxyport: 80
Proxyusername: username
Proxypassword: password
So I tried to use the global Java Proxy setup:
System.setProperty("http.proxy","proxyaddress") //... http.proxyUser, http.ProxyPassword
//and so on
It did not work.
After looking into the StandardHttpRequestor I realized I need to use this Object as well as a Proyx Object:
Proxy proxy = new Proxy(Proxy.Type.HTTP,new InetSocketAddress(ip,port));
StandardHttpRequestor requ = new StandardHttpRequestor(proxy);
Which is wrong, because it has no authentication.
For authentication, the net and google show me the following. Putting all together, my current code looks like the following:
String ip = "http://myproxy.com";
int port = 80;
final String authUser = "username";
final String authPassword = "password";
Authenticator.setDefault(new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(authUser, authPassword.toCharArray());
}
});
System.setProperty("http.proxyUser", authUser);
System.setProperty("http.proxyPassword", authPassword);
Proxy proxy = new Proxy(Proxy.Type.HTTP,new InetSocketAddress(ip,port));
StandardHttpRequestor requ = new StandardHttpRequestor(proxy);
return requ;
But this does not work as well.
What am I doing wrong?
I can't seem to get the Proxy to work.
One problem was the http:// in String ip = "http://myproxy.com";
My current code looks the following, and works sometimes. Sometimes not. I have no idea why. Sometimes I have to reallow the App to be connected to my DropBox Account, because the authKey doesn't come through the proxy...
Well at least I got an example working for you guys having the same trouble. Maybe the rest of the problem is on the proxy side? I'll have a further look into this. But here comes my code:
public HttpRequestor getProxy(){
if("true".equals(config.getProperty("proxy","false"))){
String ip = "proxy.myproxy.com";
int port = 80;
final String authUser = "username";
final String authPassword = "password";
Authenticator.setDefault(new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(authUser, authPassword.toCharArray());
}
});
Proxy proxy = new Proxy(Proxy.Type.HTTP,new InetSocketAddress(ip,port));
HttpRequestor req = new StandardHttpRequestor(proxy);
return req;
}
return null;
}
As you can see I don't use the StandardHttpRequestor anymore. For the Dropbox code it is the following:
HttpRequestor requ = con.getProxy();
if(requ!=null)
config = new DbxRequestConfig(APP_NAME, Locale.getDefault().toString(),requ);
else
config = new DbxRequestConfig(APP_NAME, Locale.getDefault().toString());
As I already said, sometimes it works. Sometimes not. I'm going to write more info about that as soon as I know if it's because of the code or because of the proxy itself.
I wonder if it is possible to connect to Hotmail with JavaMail?
I've tried this but it doesn't work, connection refused...
String host = "pop3.live.com";
String username = "laqetqetqet#hotmail.com";
String password = "rqetqetq";
Session session;
Store store;
String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
Properties pop3Props = new Properties();
pop3Props.setProperty("mail.pop3.socketFactory.class", SSL_FACTORY);
pop3Props.setProperty("mail.pop3.socketFactory.fallback", "false");
pop3Props.setProperty("mail.pop3.port", "995");
pop3Props.setProperty("mail.pop3.socketFactory.port", "995");
URLName url = new URLName("pop3", host, 995, "", username, password);
session = Session.getInstance(pop3Props, null);
store = new POP3SSLStore(session, url);
store.connect();
Anyone already succeeded to do this?
Hotmail now supports pop3 (through SSL).
Thus, you need the following settings:
pop3Props.setProperty("mail.pop3.ssl.enable",
"true");
For all other properties, you must add a "s" in the properties string (so it says "pop3s" instead of "pop3"):
pop3Props.setProperty("mail.pop3s.socketFactory.class",
SSL_FACTORY);
pop3Props.setProperty("mail.pop3s.socketFactory.fallback",
"false");
pop3Props.setProperty("mail.pop3s.port",
"995");
pop3Props.setProperty("mail.pop3s.socketFactory.port",
"995");
For me, the following code works nicely:
String host = "pop3.live.com";
String username = "laqetqetqet#hotmail.com";
String password = "rqetqetq";
Properties pop3Props = new Properties();
pop3Props.setProperty("mail.pop3s.port", "995");
Session session = Session.getInstance(pop3Props, null);
Store store = session.getStore("pop3s");
store.connect(host, 995, username, password);
You could try this SourceForge project
MrPostman is an email gateway from local POP clients like Microsoft Outlook, Mozilla's mail client etc. to different web mail services like Yahoo and Hotmail.It is being designed for extensibility so is easy to add more web mail services to it.