【问题标题】:Verify mail server connection programmatically in ColdFusion在 ColdFusion 中以编程方式验证邮件服务器连接
【发布时间】:2011-02-10 23:06:51
【问题描述】:

我正在使用自定义 SMTP 服务器,并希望在用户输入自己的服务器凭据时验证连接。

与 Adob​​e CF 和 Railo 在添加邮件服务器时允许执行的检查类型完全相同。

当然,这并不能保证 delivery 会正常工作,但至少要检查输入的服务器/用户名/密码是否有效。

我可以看到一种棘手的方法:尝试使用 cfmail 发送电子邮件并检查邮件日志。但我相信它可以做得更优雅。

标准 ACF/Railo 发行版中是否有任何 Java 库可以帮助我?我将如何使用它们?非常感谢示例。

提前致谢。

编辑:

请不要与存在的 Java 标记相混淆。 CFML 中需要解决方案。虽然它可以使用一些 Java 库(如果适用)。

【问题讨论】:

    标签: java coldfusion smtp railo cfml


    【解决方案1】:

    使用Apache Commons Net,您可以执行以下操作:

    try {
         int reply;
         client.connect("mail.foobar.com");
         System.out.print(client.getReplyString());
         // After connection attempt, you should check the reply code to verify
         // success.
         reply = client.getReplyCode();
         if(!SMTPReply.isPositiveCompletion(reply)) {
           client.disconnect();
           System.err.println("SMTP server refused connection.");
           System.exit(1);
         }
         // Do useful stuff here.
         ...
       } catch(IOException e) {
         if(client.isConnected()) {
           try {
             client.disconnect();
           } catch(IOException f) {
             // do nothing
           }
         }
         System.err.println("Could not connect to server.");
         e.printStackTrace();
         System.exit(1);
       }
    

    其中clientorg.apache.commons.net.smtp.SMTPClient 类的一个实例。上面的代码取自 SMTPClient API Docs。

    【讨论】:

    • 谢谢,至少这个类存在于 Railo 的包中,我现在可以测试连接了。虽然我找不到测试用户/通过的方法。
    【解决方案2】:

    我认为 sfussenegger 的想法是正确的。但是不是使用自定义身份验证器,而是通过 connect(..) 进行身份验证呢?只用gmail测试过。但它似乎工作。

    编辑:我用 CF9 和 OBD 成功测试了这个。不幸的是,我在 Railo 上没有运气……真可惜。

    编辑:已更新以添加缺少的“mail.smtp.auth”属性。它现在应该也可以与 Railo 一起正常工作了。

        //Java Version
        int port = 587;
        String host = "smtp.gmail.com";
        String user = "username@gmail.com";
        String pwd = "email password";
    
        try {
            Properties props = new Properties();
            // required for gmail 
            props.put("mail.smtp.starttls.enable","true");
            props.put("mail.smtp.auth", "true");
            // or use getDefaultInstance instance if desired...
            Session session = Session.getInstance(props, null);
            Transport transport = session.getTransport("smtp");
            transport.connect(host, port, user, pwd);
            transport.close();
            System.out.println("success");
         } 
         catch(AuthenticationFailedException e) {
               System.out.println("AuthenticationFailedException - for authentication failures");
               e.printStackTrace();
         }
         catch(MessagingException e) {
               System.out.println("for other failures");
               e.printStackTrace();
         }
    
    
    
    <cfscript>
        //CF Version
        port = 587;
        host = "smtp.gmail.com";
        user = "username@gmail.com";
        pwd = "email password";
    
        try {
            props = createObject("java", "java.util.Properties").init();
            props.put("mail.smtp.starttls.enable", "true");
            props.put("mail.smtp.auth", "true");
            // or use getDefaultInstance instance if desired...
            mailSession = createObject("java", "javax.mail.Session").getInstance(props, javacast("null", ""));
            transport = mailSession.getTransport("smtp");
            transport.connect(host, port, user, pwd);
            transport.close();
            WriteOutput("success");
         } 
         //for authentication failures
         catch(javax.mail.AuthenticationFailedException e) {
               WriteOutput("Error: "& e.type &" ** "& e.message);
         }
         // for other failures
         catch(javax.mail.MessagingException e) {
               WriteOutput("Error: "& e.type &" ** "& e.message);
         }
    </cfscript>
    

    【讨论】:

    • 谢谢!正是我所需要的。
    • 欢迎 :)(这里有多余的字符,因为 SO 讨厌简洁)
    • 另外,现在测试一下,即使设置错误,我也只会收到成功消息。知道为什么吗? (使用带有 1and1 的托管 SMTP,而不是 gmail)
    • @ntgCleaner -(编辑)我用错误的凭据对“smtp.1and1.com”进行了快速测试,它按预期抛出错误:错误:javax.mail.AuthenticationFailedException ** 535 身份验证凭据无效 您是否使用上面的 exact 代码并且没有抛出错误或在日志中?哪些设置 - 主机或凭据?它应该抛出一个异常,所以我想知道它是否正在被缓存/保存。连接成功至少一次后会出现这种情况吗?
    • @Leigh,非常感谢您对此进行测试!我担心,是的,信息已被缓存,因为我第一次使用正确的凭据进行了测试。我几乎使用了上面的 exact 代码(只是在transport.connect() 中更改了变量名,这些都是正确的)。我将检查释放缓存的信息。如果您知道从哪里开始,我很想听听!
    【解决方案3】:

    这并不漂亮,但可以做到:只需使用 try 将电子邮件发送到非法地址,然后查看您收到的错误消息。如果错误消息提示身份验证失败,您就知道该怎么做了。

    编辑一些工作代码:

    这里有一些用于验证 Gmail 凭据的有效代码。 Gmail 并没有抱怨非法@localhost。现在您可以尝试搜索导致异常的收件人,也可以将邮件真正发送到某个地址并立即丢弃。。编辑:甚至没有必要发送一些东西。只需连接并处理可能的 AuthenticationFailedException。

    import java.util.Properties;
    import javax.mail.AuthenticationFailedException;
    import javax.mail.MessagingException;
    import javax.mail.PasswordAuthentication;
    import javax.mail.Session;
    import javax.mail.Transport;
    
    public class Main {
    
        private static Session createSmtpSession(final String user, final String password) {
            final Properties props = new Properties();
            props.setProperty("mail.transport.protocol", "smtp");
            props.setProperty("mail.smtp.host", "smtp.gmail.com");
            props.setProperty("mail.smtp.auth", "true");
            props.setProperty("mail.smtp.port", "587");
            props.setProperty("mail.smtp.starttls.enable", "true");
    
            return Session.getDefaultInstance(props, new javax.mail.Authenticator() {
    
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(user, password);
                }
            });
        }
    
        private static boolean validateCredentials(String user, String password) {
            try {
                Transport transport = createSmtpSession(user, password).getTransport();
                transport.connect();
                transport.close();
            } catch (AuthenticationFailedException e) {
                return false;
            } catch (MessagingException e) {
                throw new RuntimeException("validate failed", e);
            }
            return true;
        }
    
        public static void main(String[] args) {
            System.out.println(validateCredentials(args[0], args[1]));
        }
    
    }
    

    【讨论】:

    • 不,如果电子邮件属性的语法正确,则不会出现任何错误:消息将被推送到池中。这就是我在谈到 mail.log 解析时在问题中提到的内容。
    • @Sergii 这是一些工作代码。不是解析日志,只是异常处理。
    • 如果没有这样的异常,SMTP 服务器很可能被配置为静默失败,这很奇怪。我怀疑 cfmail 只是在吞噬异常。
    • 抱歉,我们说的是 COLDFUSION 吗?我不能使用纯 Java 解决方案,抱歉。
    • 自从我第一次回答这个问题以来,我显然忘记了coldfusion标签。好吧,也许其他人毕竟觉得这很有用。
    猜你喜欢
    • 1970-01-01
    • 2019-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多