Pergunta

Preciso enviar centenas de newsletters, mas gostaria de verificar primeiro se existe e-mail no servidor.É chamado SMTP validação, pelo menos penso que sim, com base na minha pesquisa na Internet.

Existem diversas bibliotecas que podem fazer isso, e também uma página com código-fonte aberto em ASP Clássico (http://www.coveryourasp.com/ValidateEmail.asp#Result3), mas tenho dificuldade em ler o ASP Classic e parece que ele usa alguma biblioteca de terceiros...

Existe algum código para validação SMTP em C# e/ou explicação geral de como funciona?

Foi útil?

Solução

Esteja ciente de que a maioria dos MTAs (Mail Transfer Agent) terão o comando VRFY desativado por motivos de proteção contra spam, eles provavelmente até bloquearão você se você tentar vários RCPT TO consecutivos (veja http://www.spamresource.com/2007/01/whatever-happened-to-vrfy.html).Então mesmo que você encontre uma biblioteca para fazer essa verificação, não valerá muito.Ishmaeel está certo, a única maneira de realmente descobrir é enviando um e-mail e ver se ele retorna ou não.

@Hrvoje:Sim, estou sugerindo que você monitore e-mails rejeitados.MAS:nem todos os e-mails devolvidos devem terminar automaticamente na sua lista "não existe", você também deve diferenciar entre temporários (por exemplo,caixa de correio cheia) e erros permanentes.

Outras dicas

SMTP é um protocolo baseado em texto transportado por TCP/IP.

Seu programa de validação precisa abrir uma conexão TCP/IP com a porta 25 do servidor (SMTP), escrever em poucas linhas e ler a resposta.A validação é feita (mas nem sempre) na linha “RCTP TO” e na linha “VFRY”.

O RFC SMTP descreve como isso funciona (veja Green@Beta.ARPA abaixo, S são linhas enviadas pelo cliente, R são linhas recebidas do servidor):

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

Embora seja verdade que muitos domínios retornarão falsos positivos devido a abusos, ainda existem alguns componentes excelentes que realizarão vários níveis de validação além da validação SMTP.Por exemplo, vale a pena verificar primeiro se pelo menos o domínio existe.Estou no processo de compilar minha própria lista de recursos relacionados a esta questão, que você pode acompanhar aqui:

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

Para aqueles que desejam adicionar algo a esta lista, também incluirei o que tenho atualmente aqui:

Para um formulário à prova de balas e uma ótima experiência do usuário, é útil validar o máximo possível de aspectos do endereço de e-mail.Eu posso ver do aspNetMX validador que eles verificam:

  • a sintaxe
  • o e-mail contra uma lista de endereços de e-mail inválidos
  • o domínio contra uma lista de domínios ruins
  • uma lista de domínios de caixa de correio
  • se o domínio existe ou não
  • se existem registros MX para o domínio
  • e finalmente através de SMTP, existindo ou não uma caixa de correio

É esta última etapa que pode ser contornada pelos administradores retornando true para basicamente todas as solicitações de verificação de conta, mas na maioria dos casos, se o usuário inseriu intencionalmente um endereço incorreto, ele já foi detectado.E se houve erro do usuário na parte do domínio do endereço, isso também será detectado.

Obviamente, uma prática recomendada para usar esse tipo de serviço em uma tela ou formulário de registro seria combinar esse tipo de validação com um processo de verificação para garantir que o endereço de e-mail é válido.A grande vantagem de usar um validador de e-mail antes de um processo de verificação é que ele proporcionará uma melhor experiência geral do usuário.

Você pode tentar o código abaixo, funciona bem para mim:

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;
    }
}

Obrigado e cumprimentos Rahul Saraswat

A validação de e-mail Real(TM) está tentando enviar algo para o endereço e verificando se foi rejeitado/devolvido.Então, você apenas terá que mandá-los embora e remover os endereços que falharam da sua lista de e-mails.

Não me leve a mal, mas enviar boletins informativos para mais de um punhado de pessoas hoje em dia é um assunto bastante sério.Sim, você precisa monitorar devoluções (e-mails rejeitados) que podem ocorrer de forma síncrona durante o envio SMTP (normalmente se o servidor SMTP ao qual você está conectado for autoritativo) ou de forma assíncrona como uma mensagem de e-mail gerada pelo sistema que ocorre algum tempo após o envio SMTP foi bem-sucedido.

Lembre-se também da Lei CAN-SPAM e cumpra a lei ao enviar esses e-mails;você deve fornecer um link de cancelamento, bem como um endereço físico (para identificá-lo e permitir que os usuários enviem solicitações de cancelamento por correio tradicional, se assim desejarem).

Deixar de fazer essas coisas pode fazer com que seu IP seja roteado nulo, na melhor das hipóteses, e processado, na pior.

Você pode precisar disso Componente validador de e-mail para .NET

Aqui está o exemplo de código:


   // 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);
   }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top