質問

何百ものニュースレターを送信する必要がありますが、最初にサーバーに電子メールが存在するかどうかを確認したいと考えています。それは呼ばれています SMTP 検証、少なくとも私はインターネットでの調査に基づいてそう思います。

それを実行できるライブラリがいくつかあります。また、オープンソース コードを含むページもあります。 ASPクラシック (http://www.coveryourasp.com/ValidateEmail.asp#Result3)、しかし、ASP Classicを読むのは難しく、サードパーティのライブラリを使用しているようです...

C# で SMTP 検証を行うためのコードや、その仕組みについての一般的な説明はありますか?

役に立ちましたか?

解決

ほとんどの MTA (Mail Transfer Agent) では、スパム保護の理由から VRFY コマンドがオフになっていることに注意してください。複数の RCPT TO を連続して試行するとブロックされる可能性もあります (「 http://www.spamresource.com/2007/01/whatever-happened-to-vrfy.html)。したがって、たとえその検証を行うためのライブラリを見つけたとしても、それほど価値はありません。イシュマエルの言うことは正しい。実際にそれを知る唯一の方法は、メールを送信してバウンスするかどうかを確認することだ。

@Hrvoje:はい、拒否されたメールを監視することをお勧めします。しかし:返送されたすべてのメールが自動的に「存在しない」リストに追加されるわけではありません。また、一時的なものと区別する必要もあります(例:メールボックスがいっぱいです)と永続的なエラーが発生します。

他のヒント

SMTP は、TCP/IP 上で伝送されるテキストベースのプロトコルです。

検証プログラムは、サーバーのポート 25 (SMTP) への TCP/IP 接続を開き、数行を書き込み、答えを読み取る必要があります。検証は「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

多くのドメインが悪用により誤検知を返すことは事実ですが、SMTP 検証だけを超えたいくつかのレベルの検証を実行する優れたコンポーネントがまだいくつかあります。たとえば、少なくともドメインが存在するかどうかを最初に確認することは価値があります。私は現在、この質問に関連する独自のリソースのリストを作成中です。こちらで追跡できます。

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

このリストに追加したい人のために、現在私が持っているものもここに記載します。

完璧なフォームと優れたユーザー エクスペリエンスを実現するには、電子メール アドレスのできるだけ多くの側面を検証することが役立ちます。から見ることができます aspNetMX 彼らがチェックするバリデータ:

  • 構文
  • 不正な電子メール アドレスのリストに対する電子メール
  • ドメインを不正なドメインのリストと照合する
  • メールボックスドメインのリスト
  • ドメインが存在するかどうか
  • ドメインの MX レコードがあるかどうか
  • 最後にメールボックスが存在するかどうかに関係なく SMTP 経由で送信されます。

この最後のステップは、管理者が基本的にすべてのアカウント検証リクエストに対して true を返すことで回避できますが、ほとんどの場合、ユーザーが意図的に間違ったアドレスを入力した場合は、すでに検出されています。また、アドレスのドメイン部分でのユーザー エラーの場合も捕捉されます。

もちろん、登録画面やフォームにこの種のサービスを使用する場合のベスト プラクティスは、この種の検証と電子メール アドレスが有効であることを確認する検証プロセスを組み合わせることです。検証プロセスの前に電子メール検証ツールを使用することの素晴らしい点は、全体的なユーザー エクスペリエンスが向上することです。

以下のコードを試してみてください。私にとってはうまくいきます。

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

Rahul Saraswatに感謝します

Real(TM) 電子メール検証では、アドレスに何かを送信しようとして、それが拒否/返送されるかどうかを確認します。したがって、それらを送信し、失敗したアドレスをメーリング リストから削除するだけです。

これを誤解しないでください。ただし、最近、ニュースレターを少数の人に送信することは、かなり深刻な問題です。はい、バウンス (拒否された電子メール) を監視する必要があります。バウンス (拒否された電子メール) は、SMTP 送信中に同期的に発生する可能性があります (通常、接続している SMTP サーバーが権限のある場合)。または、送信後一定時間後に発生するシステム生成の電子メール メッセージとして非同期的に発生する可能性があります。 SMTP送信は成功しました。

また、これらの電子メールを送信するときは、CAN-SPAM 法を念頭に置き、法律に従ってください。物理的な住所だけでなく配信停止リンクも提供する必要があります (あなたを識別するためと、ユーザーが希望する場合はメールで配信停止リクエストを送信できるようにするため)。

これらのことを行わないと、良くても IP がヌルルーティングされ、最悪の場合は訴訟を起こされる可能性があります。

これが必要になるかもしれません .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);
   }
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top