سؤال

أحتاج إلى إرسال مئات الرسائل الإخبارية، ولكنني أرغب في التحقق أولاً من وجود البريد الإلكتروني على الخادم.تسمى SMTP التحقق من الصحة، على الأقل أعتقد ذلك، بناءً على بحثي على الإنترنت.

هناك العديد من المكتبات التي يمكنها القيام بذلك، بالإضافة إلى صفحة تحتوي على تعليمات برمجية مفتوحة المصدر أسب كلاسيك (http://www.coveryourasp.com/ValidateEmail.asp#Result3)، ولكنني أجد صعوبة في قراءة ASP Classic، ويبدو أنه يستخدم بعض مكتبات الطرف الثالث...

هل هناك بعض التعليمات البرمجية للتحقق من صحة SMTP في C# و/أو شرح عام لكيفية عملها؟

هل كانت مفيدة؟

المحلول

كن على علم بأن معظم MTAs (وكيل نقل البريد) سيتم إيقاف تشغيل أمر VRFY لأسباب تتعلق بالحماية من البريد العشوائي، ومن المحتمل أن يقوموا بحظرك إذا حاولت عدة RCPT TO على التوالي (راجع http://www.spamresource.com/2007/01/whatever-happened-to-vrfy.html).لذلك، حتى لو وجدت مكتبة لإجراء هذا التحقق، فلن يكون الأمر يستحق الكثير.إسماعيل على حق، والطريقة الوحيدة لمعرفة ذلك هي إرسال بريد إلكتروني ومعرفة ما إذا كان سيرتد أم لا.

@هرفوجي:نعم، أقترح عليك مراقبة رسائل البريد الإلكتروني المرفوضة.لكن:لا ينبغي أن تنتهي جميع رسائل البريد المرتدة تلقائيًا في قائمة "غير موجودة"، بل يتعين عليك أيضًا التمييز بين الرسائل المؤقتة (على سبيل المثال، ورسائل البريد الإلكتروني المرتدة).صندوق البريد ممتلئ) وأخطاء دائمة.

نصائح أخرى

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

في حين أنه من الصحيح أن العديد من النطاقات سترجع نتائج إيجابية كاذبة بسبب سوء الاستخدام، إلا أنه لا تزال هناك بعض المكونات الرائعة التي ستؤدي مستويات متعددة من التحقق تتجاوز مجرد التحقق من صحة SMTP.على سبيل المثال، من المفيد التحقق أولاً لمعرفة ما إذا كان النطاق موجودًا على الأقل.أنا بصدد تجميع قائمة الموارد الخاصة بي المتعلقة بهذا السؤال والتي يمكنك تتبعها هنا:

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

بالنسبة لأولئك الذين قد يرغبون في الإضافة إلى هذه القائمة، سأقوم أيضًا بتضمين ما لدي حاليًا هنا:

للحصول على نموذج مضاد للرصاص وتجربة مستخدم رائعة، من المفيد التحقق من صحة أكبر عدد ممكن من جوانب عنوان البريد الإلكتروني.أستطيع أن أرى من com.aspNetMX المدقق الذي يقومون بالتحقق منه:

  • بناء الجملة
  • البريد الإلكتروني مقابل قائمة عناوين البريد الإلكتروني السيئة
  • المجال مقابل قائمة المجالات السيئة
  • قائمة مجالات صندوق البريد
  • ما إذا كان المجال موجودًا أم لا
  • ما إذا كانت هناك سجلات MX للمجال
  • وأخيرًا عبر SMTP سواء كان صندوق البريد موجودًا أم لا

إنها الخطوة الأخيرة التي يمكن للمسؤولين التحايل عليها من خلال إرجاع جميع طلبات التحقق من الحساب بشكل أساسي، ولكن في معظم الحالات، إذا قام المستخدم بإدخال عنوان غير صحيح عن قصد، فسيتم اكتشافه بالفعل.وإذا كان هناك خطأ من المستخدم في جزء المجال من العنوان، فسيتم اكتشاف ذلك أيضًا.

بالطبع، تتمثل أفضل الممارسات لاستخدام هذا النوع من الخدمة لشاشة أو نموذج التسجيل في الجمع بين هذا النوع من التحقق من الصحة وعملية التحقق للتأكد من صحة عنوان البريد الإلكتروني.إن الشيء العظيم في استخدام أداة التحقق من صحة البريد الإلكتروني أمام عملية التحقق هو أنها ستوفر تجربة مستخدم أفضل بشكل عام.

يمكنك تجربة الكود أدناه فهو يعمل بشكل جيد بالنسبة لي:

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

شكرا وتحييد راهول ساراسوات

يحاول التحقق من صحة البريد الإلكتروني 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