简体   繁体   English

JavaMail SMTP凭据验证,无需实际发送电子邮件

[英]JavaMail SMTP credentials verification, without actually sending an email

Is there a way to check user SMTP server credentials without sending email, or connecting to POP/IMAP. 有没有办法检查用户SMTP服务器凭据而不发送电子邮件或连接到POP / IMAP。 Some code I tried to write, fails at it. 我尝试编写的一些代码失败了。 Can you find what is missing there. 你能找到那里缺少的东西吗?

Don't worry about Email / password. 不用担心电子邮件/密码。 I know it's there. 我知道它在那里。

NOTE : If you are trying out the code. 注意:如果您正在尝试代码。 The case 1 should pass when supplying the correct credentials. 在提供正确的凭证时,案例1应该通过。 If it fails, then someone changed the password. 如果失败,则有人更改了密码。 You should use some other email address. 您应该使用其他一些电子邮件地址。



import java.util.Properties;

import javax.mail.Authenticator;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;

public class EmailTest {

 public static void main(String[] args) {
  EmailHelper eh = new EmailHelper();

  /* GMail Setting for SMTP using STARTTLS */
  String name = "AAA";
  String email = "mymasterpainter@gmail.com";
  String smtpHost = "smtp.gmail.com";
  String serverPort = "587";
  String requireAuth = "true";
  String dontuseAuth = "false";
  String userName = email; // same as username for GMAIL
  String password = "zaq12wsx";
  String incorrectPassword = "someRandomPassword";
  String enableSTARTTLS = "true";
  String dontenableSTARTTLS = "false";

  try {
   /* only valid case */
   eh.sendMail(name, email, smtpHost, serverPort, requireAuth,
     userName, password, enableSTARTTLS);
   System.out.println("Case 1 Passed");

   /* should fail since starttls is required for GMAIL. */
   eh.sendMail(name, email, smtpHost, serverPort, requireAuth,
     userName, password, dontenableSTARTTLS);
   System.out.println("Case 2 Passed");

   /* should fail since GMAIL requires authentication */
   eh.sendMail(name, email, smtpHost, serverPort, dontuseAuth, "", "",
     dontenableSTARTTLS);
   System.out.println("Case 3 Passed");

   /* should fail. password is incorrect and starttls is not enabled */
   eh.sendMail(name, email, smtpHost, serverPort, requireAuth,
     userName, incorrectPassword, dontenableSTARTTLS);
   System.out.println("Case 4 Passed");
  } catch (MessagingException e) {
   e.printStackTrace();
  }
 }

}

class EmailHelper {

 private Properties properties = null;
 private Authenticator authenticator = null;
 private Session session = null;

 public void sendMail(String name, String email, String smtpHost,
   String serverPort, String requireAuth, String userName,
   String password, String enableSTARTTLS) throws MessagingException {
  properties = System.getProperties();
  properties.put("mail.smtp.host", smtpHost);
  properties.put("mail.smtp.port", serverPort);
  properties.put("mail.smtp.starttls.enable", enableSTARTTLS);
  properties.put("mail.smtp.auth", requireAuth);
  properties.put("mail.smtp.timeout", 20000);

  authenticator = new SMTPAuthenticator(userName, password);

  session = Session.getInstance(properties, authenticator);

  // session.setDebug(true);

  Transport tr = session.getTransport("smtp");
  tr.connect();
  /*
   * do I need more than just connect? Since when i try to send email with
   * incorrect credentials it fails to do so. But I want to check
   * credentials without sending an email. Assume that POP3/IMAP username
   * is not same as the SMTP username, since that might be one of the
   * cases
   */
 }
}

class SMTPAuthenticator extends Authenticator {

 private String userName = null;
 private String password = null;

 public SMTPAuthenticator(String userName, String password) {
  this.userName = userName;
  this.password = password;

 }

 @Override
 public PasswordAuthentication getPasswordAuthentication() {
  return new PasswordAuthentication(userName, password);
 }
}

You have this problem because of the SMTP protocol itself. 由于SMTP协议本身,您遇到此问题。 The authentication is not mandatory in the protocol. 身份验证在协议中不是必需的。 When you call the method "connect" you will do at least an "EHLO" command which returns supported extensions. 当您调用方法“connect”时,您将至少执行一个返回支持的扩展的“EHLO”命令。 Authentication is an extension defined in a RFC. 身份验证是RFC中定义的扩展。 JavaMail will try to do an "AUTH" command only if the server says it supports so and if you have provided the credentials. 只有当服务器说它支持时,如果你提供了凭据,JavaMail才会尝试执行“AUTH”命令。 The things is the Authentication extension information may be sent only after you've done a "STARTTLS" (which is also an extension) because it's not safe to use for example PLAIN authentication on a clear channel. 事情是身份验证扩展信息只有在您完成“STARTTLS”(也是一个扩展)后才能发送,因为在明确的通道上使用例如PLAIN身份验证是不安全的。 That's why JavaMail does a second "EHLO" after a "STARTTLS" to update supported extension. 这就是为什么JavaMail在“STARTTLS”之后执行第二次“EHLO”以更新支持的扩展。

So one simple solution for you problem is to always put "mail.smtp.starttls.enable" to true. 因此,一个简单的解决方案就是始终将“mail.smtp.starttls.enable”设置为true。 In JavaMail (1.4.5 at least), this means "STARTTLS" command will be sent if the server says it supports so (otherwise not) then you will get the updated extension and JavaMail may do an "AUTH" if needed. 在JavaMail(至少1.4.5)中,这意味着如果服务器说它支持,则将发送“STARTTLS”命令(否则不会),然后您将获得更新的扩展,如果需要,JavaMail可以执行“AUTH”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM