Send email OAUTH2 SMTP Outlook Java - java

I am using the scopes: mail.send, mail.readwrite, mail.read, offline_access, openid, email, and profile (although I am fairly confident I do not need all of these -> goal is to read inbox and send emails, while also getting email and name if they exist).
I am then connecting to SMTP server with the following code:
OAuth2Authenticator.connectToSmtp("smtp-mail.outlook.com",
587,
user.getOutlookUid(),
accessToken,
true);
The code that actually connects to the server is here:
public static SMTPTransport connectToSmtp(String host, int port, String userEmail, String oauthToken, boolean debug)
throws Exception {
Properties props = new Properties();
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.starttls.required", "true");
props.put("mail.smtp.sasl.enable", "true");
props.put("mail.smtp.sasl.mechanisms", "XOAUTH2");
props.put("mail.smtp.sasl.mechanisms.oauth2.oauthToken", oauthToken);
Session session = Session.getInstance(props);
session.setDebug(debug);
URLName unusedUrlName = null;
SMTPTransport transport = new SMTPTransport(session, unusedUrlName);
// If the password is non-null, SMTP tries to do AUTH LOGIN.
String password = "";
transport.connect(host, port, userEmail, password);
return transport;
}
Okay, now I can get to the most frustrating part... I have used the "connectToSMTP" method to connect to Gmail and it worked perfectly.
OAuth2Authenticator.connectToSmtp("smtp.gmail.com",
587,
user.getGoogleUid(),
accessToken,
true);
So ultimately my question is "what am I doing wrong?" or "what can I update to be able to send emails through Outlook"? I have seen that Outlook has a REST API, but that is plan B. Is there something different about Outlook vs Gmail?
Some things I have considered:
Scope did not request enough access (so I probably am asking for too much now)
access_token was stored incorrectly or encoded in some way (tried decoding it from base_64 which provided nothing). I am able to use my refresh_token to update the access_token so that tells me I am probably storing them correctly.
I tried passing null for the password. Also passed in the actual password and that WORKED, but I have the access_token and refresh_token so I shouldn't need to ask for their explicit password. Also this would be dangerous and sketchy to ask of users.
I tried manually connecting to the smtp server using "openssl s_client -crlf -starttls smtp -connect smtp-mail.outlook.com:587", but it seemed to think my access_token was wrong "535 5.0.0 OAuth failed: OAuth authentication failed due to Invalid token. Code -2147184118" That number when taken two's complement and converted to hex is 0x8004920a. Helped in searches but was to no avail.
I have done a lot of searching for this and will continue now to post this everywhere. A lot of resources for it working with Gmail, but as previously stated I already have it working for Gmail. Something seems different for Outlook. Also I have encountered lots of posts regarding email forwarding on an email client... I am semi-creating an email client so going through outlook.com settings doesn't help me.
Another concern that a buddy of mine had was that my access token was really long, contributing to what the manual smtp server claimed. It is 1188 characters long. It's something like 'EwB4Aul3BAAUo4xeBIbHjhBxWOFekj4Xy2...x9stHxi2K/VFggE=' (obviously I hid most of the characters).
Preemptive THANK YOU for anyone who offers advice or finds my issue. Especially why I can pass in the email password and that fails, but using the oauth access_token fails.

Try using "pop3://user:password#host:port/INBOX". to retrieve email from the inbox ,
more information can be found out https://javamail.java.net/docs/api/com/sun/mail/pop3/package-summary.html

hope this helps : https://technet.microsoft.com/en-ca/dn44016. Properties props = new Properties();
props.put("mail.imap.ssl.enable", "true"); // required for Gmail
props.put("mail.imap.auth.mechanisms", "XOAUTH2");
Session session = Session.getInstance(props);
Store store = session.getStore("imap");
store.connect("imap.gmail.com", username, oauth2_access_token);

Related

Unable to connect to gmail via Gmail API. How can we turn on Less secure app access?

I am connecting to the gmail account to verify the confirmation emails sent by our application. When implementing it originally, in order to connect to gmail successfully, we had to set the account with 'Less secure app access' configuration to ON.
Looks like google turned that setting to off now from May 30,2022 and so the authentication is failing now.
How can I connect to Gmail account to verify the confirmation emails now?
java.lang.RuntimeException: javax.mail.AuthenticationFailedException: [AUTHENTICATIONFAILED] Invalid credentials (Failure)
You could try authentification via "App password".
On your Google account:
set "2-Step Verification" ON
2-Step Verification
create 16-character "App password"(
How to create app password) -> result should be similar to:
16-character "App password"
Instead of Google account password use 16-character password
MailMessage mail = new MailMessage();
foreach (string receiver in DolociPrejemnike())
mail.To.Add(receiver);
mail.From = new MailAddress("app_gmail#gmail.com", "No replay"); //poĊĦiljatelj (vedno enak)
mail.Subject = SetSubject();
mail.Body = SetBody();
mail.IsBodyHtml = true;
SmtpClient smtp = new SmtpClient();
smtp.Host = "smtp.gmail.com";
smtp.Port = 587;
smtp.UseDefaultCredentials = true;
smtp.Credentials = new System.Net.NetworkCredential("app_gmail#gmail.com", "xtqapucsmyvqmvxp"); // Enter seders User name and password
smtp.EnableSsl = true;
smtp.Send(mail);
I was also fighting with this for some time. When I started to use an app password it fails with the same exception as it was mentioned in the question.
After several attempts I logged in to my mail box in a browser and it asked me to authenticate again saying "There was some strange activity observed". Unexpectedly after this browser login the same piece of code started to work correctly authenticating successfully.
You can create an apps password and use that in place of your standard google password How to create a Apps Password for connecting to Google's SMTP server.
Or
You will need to enable xoauth2 in your code or if you have a workspace account go though the gmail api using a service account.
OAuth2 Support
Properties props = new Properties();
props.put("mail.imap.ssl.enable", "true"); // required for Gmail
props.put("mail.imap.auth.mechanisms", "XOAUTH2");
Session session = Session.getInstance(props);
Store store = session.getStore("imap");
store.connect("imap.gmail.com", username, oauth2_access_token);

Where should i store credentials and how get them back?

i'm developping a web application in java. During develop of email sender i have to specify credentials (email and password) of my host.
i was doing something like this:
public void sendEmail(String toAddress,
String subject, String message) throws AddressException,
MessagingException {
// sets SMTP server properties
Properties properties = new Properties();
properties.put("mail.smtp.host", smtp.gmail.com);
properties.put("mail.smtp.port", 587);
properties.put("mail.smtp.auth", "true");
properties.put("mail.smtp.starttls.enable", "true");
// Sender's email ID needs to be mentioned
final String username = "user_mail";
final String password = "password_mail";
// creates a new session with an authenticator
Authenticator auth = new Authenticator() {
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
};
Session session = Session.getInstance(properties, auth);
// creates a new e-mail message
Message msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(username));
InternetAddress[] toAddresses = { new InternetAddress(toAddress) };
msg.setRecipients(Message.RecipientType.TO, toAddresses);
msg.setSubject(subject);
msg.setSentDate(new Date());
// set plain text message
msg.setText(message);
// sends the e-mail
Transport.send(msg);
}
i think that the better practice to use credentials is to save them in an xml file, and calling them back using some method, maybe Context's method.
Can someone explain me (or give me some link where i can see) how can i do that or some better?
any help will be appreciated.
One interesting way to do it is to use Vault. It's a system for managing "secrets" like credentials, API keys, etc.
There are other things you can do like write some code to automatically encrypt and decrypt the password.
As a rule of thumb, it's also important to make sure that you don't install the JDK on a production machine. If you do, a hacker would get access to javap which is the Java disassembler. The output wouldn't be that good, but probably enough to get a ballpark idea of the method you are using to secure the password.
It depends how much effort you want to place in the hiding the secrets. At the end - you have to store the credentials somewhere. You can encrypt them, but you have to store the encryption key somewhere anyway.
Many (even mature) systems simply store the username / password as plains in a configuration file and rely on the hosting to make the system secure. Some systems encrypt the passwords, but the encryption key is available anyway somewhere in a confguration and keystore. It makes retrieving your email password a little bit more complex, but not much.
The most secure way I've seen was creating a key based on a configured secret (password) and some environment property (IP, MAC, ...).
So - lets be practical. Storing your SYSTEM credentials as plains in most of the cases may be ok. You have to secure access to your system so there should be no way to get the configuration file.

Spring java mail : send mail impossible with yahoo

I am trying to user spring java mail with theses properties :
mail:
host: smtp.mail.yahoo.com
port: 587
username: xxx
password: xxx
protocol: smtp
properties.mail.smtp:
auth: true
starttls.enable: true
Code :
#Inject
private JavaMailSenderImpl javaMailSender;
...
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
message.setTo(to);
message.setFrom(fromEmail);
message.setSubject(subject);
message.setText(content, isHtml);
javaMailSender.send(mimeMessage);
But I am getting this error when I send the mail :
E-mail could not be sent to user 'xxx#yahoo.fr', exception is:
Authentication failed; nested exception is
javax.mail.AuthenticationFailedException: 535 5.7.0 (#MBR1212)
Incorrect username or password.
I am sure my login/pwd are correct.
Are my properties incorrect?
Check your username / password, are you parsing it with plain text,string variable or char array, does it contains special character that needed to be escaped?
Make sure there is no empty space, extra space/break.
Your code and config are too narrow ,we can't help much to be honest.
Are you able to send email using gmail account or other email?
If you do so, there are problems in either yahoo config,such as port or
the username password are indeed really incorrect.
This is most likely Yahoo's new sign in method restrictions.
Try this:
https://help.yahoo.com/kb/mail-for-desktop/turn-account-key-sln25781.html
or this:
https://login.yahoo.com/account/security#less-secure-apps
Yes I am also using Yahoo mail and connecting with Java mail, you need to set up a third party access key, and then you will be able to connect.

See attributes of currently connected Ldap user

I connect to an LDAP server as Bob:
Hashtable props = new Hashtable();
props.put(Context.SECURITY_PRINCIPAL, "cn=Bob,cn=Users,dc=myCompany,dc=com");
props.put(Context.SECURITY_CREDENTIALS, "Password1");
props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
props.put(Context.PROVIDER_URL, url);
InitialLdapContext context = new InitialLdapContext(props, null);
Now I want to see Bob's name and email address.
I was expecting to find a method on context to return the attributes of the currently connected user, but I can't find one.
Bob doesn't have permission to search the directory, so I can't use context.search after connecting.
Is there a way to get these attributes without making another call to the LDAP server, or having to connect as someone else first?
You need to use the RFC 4532 'whoami' extended operation, OID=1.3.6.1.4.1.4203.1.11.3. You'll need to write yourself an ExtendedRequest and ExtendedResponse class for that (sorry can't post mine, but it's simple), and use it as follows:
WhoAmIExtendedResponse response = (WhoAmIExtendedResponse)context.extendedOperation(new WhoAmIExtendedRequest());
and then get the authZId out of the response. That's the DN of the current user, prefixed by "dn:". You then get his attributes via context.getAttributes("...")

Java Mail API password Verification

I am using Java Mail API to send an email. So I am getting email and password from user, I just want to check the password when they are enter their password, but I don't get any ideas to verify the password in Java Mail API. Can anyone help?
Question 2:
protected PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication("xxx#gmail.com","*");
}
What is use of the above the above method
To validate the password you have to use it. You don't have to send a message, but you do have to connect to the server and authenticate. Use the Transport.connect method. You can close the connection right away if you're not going to send the message soon, or you can save the Transport object for use later when you send the message and close it when you're done. Note that if you're waiting for user input between the Transport.connect (to validate the password) and the Transport.sendMessage (to send the message), the server may time out the connection and you'll have to reconnect before sending.

Categories

Resources