Программно проверьте соединение с почтовым сервером в ColdFusion

Я использую пользовательские SMTP-серверы и хотел бы проверить соединение, когда пользователь вводит свои собственные учетные данные сервера.

Точно такую ​​же проверку позволяют делать Adobe CF и Railo при добавлении почтового сервера.

Конечно, это не гарантирует, что доставка будет работать, но, по крайней мере, проверяет правильность введенного сервера/имени пользователя/пароля.

Я вижу один хитрый способ: попробуйте отправить электронное письмо с помощью cfmail и проверьте журнал почты. Но я считаю, что это можно сделать более элегантно.

Есть ли какая-нибудь библиотека Java, доступная в стандартном дистрибутиве ACF/Railo, которая мне поможет? Как бы я их использовал? Примеры высоко ценятся.

Заранее спасибо.

ИЗМЕНИТЬ:

Пожалуйста, не путайте с присутствующим тегом Java. Требуется решение в CFML. Хотя он может использовать некоторые библиотеки Java, если это применимо.


person Sergey Galashyn    schedule 22.04.2010    source источник


Ответы (3)


Думаю, у Сфуссенеггера правильная идея. Но вместо того, чтобы использовать собственный аутентификатор, как насчет аутентификации через connect(..)? Проверено только с gmail. Но, похоже, это работает.

EDIT: я успешно протестировал это с CF9 и OBD. К сожалению, с Райло мне не повезло... облом.

РЕДАКТИРОВАНИЕ: добавлено отсутствующее свойство mail.smtp.auth. Теперь он должен корректно работать и с Railo.

    //Java Version
    int port = 587;
    String host = "smtp.gmail.com";
    String user = "[email protected]";
    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 = "[email protected]";
    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>
person Leigh    schedule 23.04.2010
comment
Спасибо! Именно то, что мне нужно. - person Sergey Galashyn; 16.05.2010
comment
Добро пожаловать :) (здесь лишние символы, потому что SO ненавидит краткость) - person Leigh; 19.05.2010
comment
Кроме того, тестируя это сейчас, я получаю только сообщения об успехе, даже если настройки неверны. Есть идеи, почему? (Используя размещенный SMTP с 1 и 1, а не с gmail) - person ntgCleaner; 10.02.2016
comment
@ntgCleaner - (Изменить) Я провел быстрый тест на smtp.1and1.com с неверными учетными данными, и он выдает ошибку, как и ожидалось: Ошибка: javax.mail.AuthenticationFailedException ** 535 Недопустимые учетные данные для аутентификации Вы используете exact< /i> код выше и никаких ошибок не возникает или в журналах? Какие настройки - хост или учетные данные? Он должен вызывать исключение, поэтому мне интересно, может быть, он кэшируется/сохраняется. Это происходит после успешного подключения хотя бы один раз? - person Leigh; 10.02.2016
comment
@Leigh, большое спасибо за тестирование! У меня есть опасения, что да, информация была кэширована, потому что я тестировал с правильными учетными данными в первый раз. Я использовал в значительной степени точный код выше (просто изменил имена переменных в transport.connect(), все они правильные). Я проверю возможность публикации кэшированной информации. Если у вас есть идея, с чего начать, я буду рад услышать! - person ntgCleaner; 10.02.2016
comment
@Leigh, я добавил очистку кеша при уничтожении приложения, теперь оно работает. Спасибо за указатель в правильном направлении! - person ntgCleaner; 11.02.2016
comment
@ntgCleaner - Значит, экземпляр transport кэшировался? Это объяснило бы результаты, если экземпляр транспорта кэширует данные соединения. Спасибо за продолжение! - person Leigh; 11.02.2016

Используя 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);
   }

Где client — это экземпляр org.apache.commons.net.smtp.SMTPClient. Вышеприведенный код был взят из документации API SMTPClient.

person folone    schedule 22.04.2010
comment
Спасибо, по крайней мере, этот класс присутствует в пакете Railo, и теперь я могу проверить соединение. Хотя я не могу найти способ проверить пользователя/прохождение. - person Sergey Galashyn; 22.04.2010

Это некрасиво, но может подойти: просто попробуйте отправить электронное письмо на недопустимый адрес и посмотрите, какое сообщение об ошибке вы получите. Если сообщение об ошибке жалуется на неудачную аутентификацию, вы знаете, что делать.

РЕДАКТИРОВАТЬ некоторый рабочий код:

вот некоторый рабочий код для проверки учетных данных 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]));
    }

}
person sfussenegger    schedule 22.04.2010
comment
Нет, ошибок не будет, если атрибуты электронной почты имеют правильный синтаксис: сообщение будет отправлено в пул. Это то, что я упомянул в своем вопросе, когда рассказал о разборе mail.log. - person Sergey Galashyn; 22.04.2010
comment
@Sergii, вот рабочий код. Речь идет не о разборе журналов, а только об обработке исключений. - person sfussenegger; 22.04.2010
comment
если такого исключения нет, SMTP-сервер, скорее всего, настроен на тихий сбой, что было бы довольно странно. Я подозреваю, что cfmail просто проглатывает исключение. - person sfussenegger; 22.04.2010
comment
Извините, мы говорим о COLDFUSION? Я не могу использовать чистое решение Java, извините. - person Sergey Galashyn; 22.04.2010
comment
Очевидно, я забыл о теге coldfusion, так как впервые ответил на вопрос. Ну, может быть, кому-то это все-таки покажется полезным. - person sfussenegger; 22.04.2010