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.
Related
I use Java NIO secured by SSL to connect client and server. To connect to a server the user is prompted to enter host, port, username and password. So far I can connect client and server (they successfully complete their SSL handshake) and I could theoretically start sending data back and forth. I have not written a mechanism to verify login credentials (username, password) yet.
The server can authenticate username and password by looking them up in a database. If the credentials a client sends are incorrect, the connection will be closed.
Question 1: When should the credentials be validated? I assume this has to happen after the SSL handshake.
Question 2: How do I securely package the credentials before they are serialized and sent to the server? I assume I should hash the password. Should I hash the username too?
Would something simple like this suffice?
public class LoginCredentials implements Serializable {
private static final long serialVersionUID = 1026410425432118798L;
private final String username;
private final byte[] passwordHash;
public LoginCredentials(String username, byte[] passwordHash) {
this.username = username;
this.passwordHash = passwordHash;
}
public final String getUsername() {
return username;
}
public final byte[] getPasswordHash() {
return passwordHash;
}
}
Question 3: Authenticating credentials should be done once per session, correct? I read some posts that seemed to indicate the credentials should be verified for every request.
Question 4: Which hashing algorithm should I use? SHA–512 seems to be very popular.
of course that after ssl handshake, when the ssl connection is established, this makes it more secure
Not many applications really do that, most of them just sends the password over ssl not hashing it at all. Yes, you can generate a hash, but the hash should be generated for every login, so it will not be always the same, this requires some code on client side to resolve some challenge which includes the correct password and some random thing sent by server, otherwise it would not differ much from regular password authentication. But there is plenty of authentication mechanisms - passwords, hashes, tokens, ssl certificates to name a few.
you need to check if the authenticated user has access rights to the resource He tries to access - this is for every request, not to login the user for every request if you have session. If you need to manage the user access rights to grant or revoke access during single session then you need to read the user access rights for every request, if you don't need such granularity then reading them once for the whole session is ok. Sometimes there are sessionless services eg. some REST, then typically you need to send some credentials on every call.
You can use any hashing algorithm that's not too easy to decipher.
I'm using Javamail to connect to an AWS email service; I've tested that I can receive emails using this code, but I would also like to get a response with data about the sent email, such as the Message ID, which AWS uses to uniquely identify a message.
I'm using MimeMessage to create an email and I am sending it with this code within a try catch block:
transport.sendMessage(message, message.getAllRecipients)
This code just fires off an email to the AWS server and I can't get any metadata back. Is there a way to listen for a response to see if the message was successful so I can retrieve the Message ID?
If the sendMessage method returns, the server accepted the message. Note that that doesn't necessarily mean it will be delivered to the recipient, however. But at that point you can use the getMessageID method to retrieve the message ID.
If the send method throws an exception, the server refused to accept the message for some reason and it won't be sent.
add properties mail.smtp.reportsuccess and mail.smtp.sendpartial to you java Mail Properties, you will get SMTPAddressSucceededException if send email success or SMTPAddressFailedException in fail.
javamail doc
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);
I have an online form that allows users to email a complaint to the company. To test it I have used gmail smtp as my host. I have no problem receiving the message to the designated email account when the sender is also a gmail but I want the "From" to not be limited to just gmail accounts. It appears that smtp is only good for sending emails from the same server?
Example: My form works great if the from is abc#gmail.com and the company email is company#gmail.com.
However if xyz#yahoo.com is entered for the sender, the receiver company#gmail.com never gets it.
Any help would be greatly appreciated. I can provide my code as well if that is needed.
Your problem is a common security restriction when using SMTP. Outgoing SMTP email can only contain a "mail from" address belonging to the sender. If you break this rule, your email may be considered SPAM.
The following will allow your recipient to reply to an alternate address.
Properties properties = new Properties();
props.put("mail.smtp.from", "abc#gmail.com");
Session session = Session.getDefaultInstance(props, null);
MimeMessage m = new MimeMessage(session);
m.addFrom(InternetAddress.parse("xyz#yahoo.com"));
m.setReplyTo(InternetAddress.parse("xyz#yahoo.com"));
See also
http://www.mkyong.com/java/javamail-api-sending-email-via-gmail-smtp-example/
http://www.openspf.org/Best_Practices/Webgenerated
Well you will have to own the other email as well as set it to work with gmail,
Check here for more details.
It's probably better to send the message to your company's mail server using the identity of the user who owns the application on the server, and include the information that the customer provides in the online form as data in the message you send. The message won't look like it came from the customer, but then it really didn't come from the customer since it wasn't sent using the customer's mail server.
We are developing a simple web application in JSF in which there is a need to include a "forget password" module. For the sake of demonstration and simplicity, I tried the following code in Java Servlet. It can send a mail to Gmail and works just fine there is no problem at all. The following is the complete Servlet code.
public class MailClient extends HttpServlet {
private class SMTPAuthenticator extends Authenticator {
private PasswordAuthentication authentication;
public SMTPAuthenticator(String login, String password) {
authentication = new PasswordAuthentication(login, password);
}
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return authentication;
}
}
protected void processRequest(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
String from = "bhaveshp1980#gmail.com";
String to = "bhaveshp1980#gmail.com";
String subject = "A mail from Java.";
String message = "My first mail from Java.";
String login = "bhaveshp1980#gmail.com";
String password = "password";
Properties props = new Properties();
props.setProperty("mail.host", "smtp.gmail.com");
props.setProperty("mail.smtp.port", "587");
props.setProperty("mail.smtp.auth", "true");
props.setProperty("mail.smtp.starttls.enable", "true");
Authenticator auth = new SMTPAuthenticator(login, password);
Session session = Session.getInstance(props, auth);
MimeMessage msg = new MimeMessage(session);
try {
msg.setText(message);
msg.setSubject(subject);
msg.setFrom(new InternetAddress(from));
msg.addRecipient(Message.RecipientType.TO,
new InternetAddress(to));
Transport.send(msg);
} catch (MessagingException ex) {
Logger.getLogger(MailClient.class.getName()).
log(Level.SEVERE, null, ex);
}
} finally {
out.close();
}
}
#Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response);
}
#Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response);
}
#Override
public String getServletInfo() {
return "Short description";
}
}
Now, the first question is that as soon as a user enters his valid email address, a verification code should be submitted to a specific message server (Gmail, Yahoo and so on) without asking the user for his password (Which is not the case of the above code) which is essential in implementing the "forget password" module in a web application.
The second question is that the above code is bound to sending a mail only to Gmail. If I want to send a mail to some other message server say Yahoo, the statement
props.setProperty("mail.host", "smtp.gmail.com");
needs to be changed to
props.setProperty("mail.host", "smtp.mail.yahoo.com");
[and port no too, regarding others] means that a specific message server to which a message has to be sent need to be recognized properly. Which is the best way to do so?. What is the best method(s) to overcome these issues, please.
Do you change your SMTP settings in your email client each time you send a mail to a different mail provider? No. You don't set the SMTP server to gmail when sending a mail to a gmail.com address. And then set it to yahoo when sending a mail to a yahoo.com address. You set it to your email provider SMTP server, and this SMTP server sends the mail to the appropriate location.
Just choose an SMTP server which agrees to send mails from your application. Sending a dozen per day will be OK with any SMTP provider. But if you send thousands a day, then you could have problems with your provider. Just ask your hosting provider how it goes with outgoing mails (how much it costs, how many per day are accepted, is there a bandwidth limit, etc.)
So you can't do that. That's the whole point of keeping people from spamming, masquerading as users they aren't, and lots of other nasty things.
You need to setup a SMTP server or get your domain hosted on a mail service that you can send mail through. Maybe your ISP or hosting provider provides this already and you just need to sign up for that. Otherwise, there are plenty of places out there that will allow you to send mail from your domain. I use:
http://www.authsmtp.com/
Or you can have google host your domain for free, but they put a limit on the number of messages you can send per day which last time I checked was like 100. So if your site plans on sending more mail than that you need to bump up to paid service like authsmtp.
http://www.google.com/apps/intl/en/business/smb/email.html#utm_campaign=en&utm_source=en-ha-na-us-sk&utm_medium=ha&utm_term=%2Bemail%20%2Bhosting
Basically you need to find a mail server that is in charge of your MX record so emails sent to your domain will get routed to those servers, and so you application can send email from your domain and not get black listed as a spammer because you are doing naughty things.
While you can setup your own smtp server it's just so much easier to use a service, and that gives you a professional look for doing things like customer service, and responding to people when you mail comes from a domain associated with your website and not some johnnyappleseed#gmail.com
You need to do some basic research about how email works from a technical perspective as well. That will help you understand why what I'm talking about is important.
The authentication part you cannot get around. This is configured in the remote server, so unless you use your own mailserver, you have to do what gmail asks you to do. But instead of hardcoding the login/password, you could store them in an (encrypted?) properties file and modify that whenever you want to use another mailserver.
You need to generate a random token and send it as part of the
message. You store the token in the database with an association to
the user's profile. When the user returns to your site with that
token (by entering it into a form, or by clicking a link with that
token as GET parameter) you can be sure the user is authentic and
offer the reset password dialog.
Don't send the message to the smtp server of the recipient, but to
the smtp server of your from email address. So sending it to gmail
would be fine. I would make stmp host url, username and password
configurable, e.g. in a property file.