Email SMTP validator - PullRequest
       10

Email SMTP validator

15 голосов
/ 26 августа 2008

Мне нужно отправить сотни новостных рассылок, но я хотел бы сначала проверить, существует ли электронная почта на сервере. Это называется SMTP валидация, по крайней мере, мне так кажется, основываясь на моих исследованиях в Интернете.

Есть несколько библиотек, которые могут сделать это, а также страница с открытым исходным кодом в ASP Classic (http://www.coveryourasp.com/ValidateEmail.asp#Result3),, но мне трудно читать ASP Classic, и кажется, что это использует стороннюю библиотеку ...

Есть ли какой-нибудь код для проверки SMTP в C # и / или общее объяснение того, как это работает?

Ответы [ 7 ]

18 голосов
/ 26 августа 2008

Имейте в виду, что большинство MTA (Mail Transfer Agent) отключают команду VRFY по соображениям защиты от спама, они, вероятно, даже заблокируют вас, если вы попробуете несколько RCPT TO подряд (см. http://www.spamresource.com/2007/01/whatever-happened-to-vrfy.html). даже если вы найдете библиотеку для такой проверки, это не будет стоить много. Измаил прав, единственный способ действительно узнать это - отправить электронное письмо и посмотреть, отскочил он или нет.

@ Hrvoje: Да, я предлагаю вам отслеживать отклоненные электронные письма. НО: не все отклоненные письма должны автоматически попадать в ваш список «не существует», вы также должны различать временные (например, полный почтовый ящик) и постоянные ошибки.

10 голосов
/ 26 августа 2008

SMTP - это текстовый протокол, передаваемый по TCP / IP.

Ваша программа проверки должна открыть TCP / IP-соединение с портом 25 сервера (SMTP), написать несколько строк и прочитать ответ. Проверка выполняется (но не всегда) в строке «RCTP TO» и в строке «VFRY».

SMTP RFC описывает, как это работает (см. Green@Beta.ARPA ниже, S - строки, отправленные клиентом, R - строки, полученные с сервера):

Example of the SMTP Procedure

         This SMTP example shows mail sent by Smith at host Alpha.ARPA,
         to Jones, Green, and Brown at host Beta.ARPA.  Here we assume
         that host Alpha contacts host Beta directly.

            S: MAIL FROM:
            R: 250 OK

            S: RCPT TO:
            R: 250 OK

            S: RCPT TO:
            R: 550 No such user here
4 голосов
/ 14 ноября 2008

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

http://delicious.com/dworthley/email.validation

Для тех, кто захочет добавить в этот список, я также включу то, что у меня сейчас есть:

Для пуленепробиваемой формы и отличного пользовательского опыта полезно проверить как можно больше аспектов адреса электронной почты. Я вижу из валидатора aspNetMX , что они проверяют:

  • синтаксис
  • электронное письмо со списком неверных адресов электронной почты
  • домен против списка плохих доменов
  • список доменов почтовых ящиков
  • существует ли домен
  • есть ли MX записи для домена
  • и, наконец, через SMTP, существует ли почтовый ящик

Это последний шаг, который может быть обойден администраторами, возвращая значение true практически всем запросам на подтверждение учетной записи, но в большинстве случаев, если пользователь намеренно ввел неверный адрес, он уже был обнаружен. И если это была ошибка пользователя в доменной части адреса, то это тоже будет обнаружено.

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

3 голосов
/ 18 февраля 2014

Вы можете попробовать приведенный ниже код, он отлично работает для меня:

public class EmailTest {
    private static int hear(BufferedReader in) throws IOException {
        String line = null;
        int res = 0;

        while ((line = in.readLine()) != null) {
            String pfx = line.substring(0, 3);
            try {
                res = Integer.parseInt(pfx);
            } catch (Exception ex) {
                res = -1;
            }
            if (line.charAt(3) != '-')
                break;
        }

        return res;
    }

    private static void say(BufferedWriter wr, String text) throws IOException {
        wr.write(text + "\r\n");
        wr.flush();

        return;
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    private static ArrayList getMX(String hostName) throws NamingException {
        // Perform a DNS lookup for MX records in the domain
        Hashtable env = new Hashtable();
        env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");
        DirContext ictx = new InitialDirContext(env);
        Attributes attrs = ictx.getAttributes(hostName, new String[] { "MX" });
        Attribute attr = attrs.get("MX");

        // if we don't have an MX record, try the machine itself
        if ((attr == null) || (attr.size() == 0)) {
            attrs = ictx.getAttributes(hostName, new String[] { "A" });
            attr = attrs.get("A");
            if (attr == null)
                throw new NamingException("No match for name '" + hostName + "'");
        }
        /*
         Huzzah! we have machines to try. Return them as an array list
         NOTE: We SHOULD take the preference into account to be absolutely
         correct. This is left as an exercise for anyone who cares.
         */
        ArrayList res = new ArrayList();
        NamingEnumeration en = attr.getAll();

        while (en.hasMore()) {
            String mailhost;
            String x = (String) en.next();
            String f[] = x.split(" ");
            // THE fix *************
            if (f.length == 1)
                mailhost = f[0];
            else if (f[1].endsWith("."))
                mailhost = f[1].substring(0, (f[1].length() - 1));
            else
                mailhost = f[1];
            // THE fix *************
            res.add(mailhost);
        }
        return res;
    }

    @SuppressWarnings("rawtypes")
    public static boolean isAddressValid(String address) {
        // Find the separator for the domain name
        int pos = address.indexOf('@');

        // If the address does not contain an '@', it's not valid
        if (pos == -1)
            return false;

        // Isolate the domain/machine name and get a list of mail exchangers
        String domain = address.substring(++pos);
        ArrayList mxList = null;
        try {
            mxList = getMX(domain);
        } catch (NamingException ex) {
            return false;
        }

        /*
        Just because we can send mail to the domain, doesn't mean that the
        address is valid, but if we can't, it's a sure sign that it isn't
        */
        if (mxList.size() == 0)
            return false;

        /* 
        Now, do the SMTP validation, try each mail exchanger until we get
        a positive acceptance. It *MAY* be possible for one MX to allow
        a message [store and forwarder for example] and another [like
        the actual mail server] to reject it. This is why we REALLY ought
        to take the preference into account.
        */
        for (int mx = 0; mx < mxList.size(); mx++) {
            boolean valid = false;
            try {
                int res;
                //
                Socket skt = new Socket((String) mxList.get(mx), 25);
                BufferedReader rdr = new BufferedReader(new InputStreamReader(skt.getInputStream()));
                BufferedWriter wtr = new BufferedWriter(new OutputStreamWriter(skt.getOutputStream()));

                res = hear(rdr);
                if (res != 220)
                    throw new Exception("Invalid header");
                say(wtr, "EHLO rgagnon.com");

                res = hear(rdr);
                if (res != 250)
                    throw new Exception("Not ESMTP");

                // validate the sender address
                say(wtr, "MAIL FROM: <tim@orbaker.com>");
                res = hear(rdr);
                if (res != 250)
                    throw new Exception("Sender rejected");

                say(wtr, "RCPT TO: <" + address + ">");
                res = hear(rdr);

                // be polite
                say(wtr, "RSET");
                hear(rdr);
                say(wtr, "QUIT");
                hear(rdr);
                if (res != 250)
                    throw new Exception("Address is not valid!");

                valid = true;
                rdr.close();
                wtr.close();
                skt.close();
            } catch (Exception ex) {
                // Do nothing but try next host
                ex.printStackTrace();
            } finally {
                if (valid)
                    return true;
            }
        }
        return false;
    }

    public static void main(String args[]) {
        String testData[] = { "rahul.saraswat@techblue.com", "rahul.saraswat@techblue.co.uk", "srswt.rahul12345@gmail.com",
        "srswt.rahul@gmail.com" };
        System.out.println(testData.length);
        for (int ctr = 0; ctr < testData.length; ctr++) {
            System.out.println(testData[ctr] + " is valid? " + isAddressValid(testData[ctr]));
        }
        return;
    }
}

Спасибо и С уважением Рахул Сарасват

2 голосов
/ 26 августа 2008

Не поймите это неправильно, но рассылка информационных бюллетеней более чем горстке людей в наши дни - довольно серьезный вопрос. Да, вам необходимо отслеживать отскоки (отклоненные электронные письма), которые могут происходить синхронно во время отправки SMTP (обычно, если SMTP-сервер, к которому вы подключены, является авторитетным) или асинхронно, как сгенерированное системой сообщение электронной почты, которое происходит некоторое время после отправка SMTP выполнена успешно.

Кроме того, при отправке этих писем учитывайте закон CAN-SPAM и соблюдайте закон; Вы должны предоставить ссылку для отмены подписки, а также физический уличный адрес (чтобы идентифицировать вас и t0 разрешать пользователям отправлять неподписанные запросы по обычной почте, если они того пожелают).

Невыполнение этих действий может привести к неправильной маршрутизации вашего IP-адреса и к худшему.

2 голосов
/ 26 августа 2008

Проверка подлинности электронной почты Real (TM) пытается отправить что-то на адрес и посмотреть, отклонено ли оно / отклонено. Таким образом, вам просто нужно отослать их и удалить адреса, которые не были найдены в вашем списке рассылки.

1 голос
/ 09 мая 2010

Вам может понадобиться Компонент проверки электронной почты для .NET

Вот пример кода:


   // Create a new instance of the EmailValidator class.
   EmailValidator em = new EmailValidator();
   em.MessageLogging += em_MessageLogging;
   em.EmailValidated += em_EmailValidationCompleted;
   try
   {
       string[] list = new string[3] { "test1@testdomain.com", "test2@testdomain.com", "test3@testdomain.com" };
       em.ValidateEmails(list);
   }
   catch (EmailValidatorException exc2)
   {
       Console.WriteLine("EmailValidatorException: " + exc2.Message);
   }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...