Validation 电子邮件SMTP验证程序
我需要发送数百份新闻稿,但想先检查服务器上是否存在电子邮件。根据我在互联网上的研究,这叫做验证,至少我认为是这样 有几个库可以做到这一点,还有一个在()中包含开源代码的页面,但我很难阅读ASP Classic,而且它似乎使用了一些第三方库Validation 电子邮件SMTP验证程序,validation,email,Validation,Email,我需要发送数百份新闻稿,但想先检查服务器上是否存在电子邮件。根据我在互联网上的研究,这叫做验证,至少我认为是这样 有几个库可以做到这一点,还有一个在()中包含开源代码的页面,但我很难阅读ASP Classic,而且它似乎使用了一些第三方库 是否有一些用于C#中SMTP验证的代码和/或其工作原理的一般说明?真正的(TM)电子邮件验证是尝试向该地址发送内容,并查看其是否被拒绝/反弹。因此,您只需将它们发送出去,并从邮件列表中删除失败的地址。SMTP是通过TCP/IP传输的基于文本的协议 您的验证程序
是否有一些用于C#中SMTP验证的代码和/或其工作原理的一般说明?真正的(TM)电子邮件验证是尝试向该地址发送内容,并查看其是否被拒绝/反弹。因此,您只需将它们发送出去,并从邮件列表中删除失败的地址。SMTP是通过TCP/IP传输的基于文本的协议 您的验证程序需要打开到服务器端口25(SMTP)的TCP/IP连接,写几行并读取答案。验证在“RCTP TO”行和“VFRY”行上完成(但并非始终如此) 描述了其工作原理(请参见Green@Beta.ARPA下面,S是客户端发送的行,R是从服务器接收的行): SMTP过程的示例 此SMTP示例显示Smith在主机Alpha.ARPA上发送的邮件, 致主机Beta.ARPA上的琼斯、格林和布朗。这里我们假设 该主机Alpha直接与主机Beta联系。 S:邮寄地址: R:250可以 S:RCPT至: R:250可以 S:RCPT至: R:550这里没有这样的用户 请注意,由于垃圾邮件保护的原因,大多数MTA(邮件传输代理)都会关闭VRFY命令,如果您连续尝试几个RCPT,它们甚至可能会阻止您(请参阅)。所以,即使你找到了一个库来进行验证,它也不会值很多钱。以实玛利是对的,要真正找到答案,唯一的办法就是发一封电子邮件,看看它是否反弹
@是的,我建议你监视被拒绝的电子邮件。但是:并非所有被退回的邮件都会自动出现在您的“不存在”列表中,您还必须区分临时错误(例如邮箱已满)和永久错误。请不要误会,但现在向少数人发送时事通讯是一件相当严重的事情。是的,您需要监视反弹(拒绝的电子邮件),反弹可以在SMTP发送期间同步发生(通常如果您连接的SMTP服务器是权威的),也可以作为系统生成的电子邮件异步发生,在SMTP发送成功后一段时间内发生 在发送这些电子邮件时,还应牢记《反垃圾邮件法》,并遵守法律;你必须提供一个不明嫌犯链接和一个实际的街道地址(以识别你和t0,允许用户通过蜗牛邮件发送不明嫌犯请求,如果他们选择的话)
如果不这样做,你的IP空地址最多只能被路由,最坏只能被起诉。虽然许多域确实会因为滥用而返回误报,但仍然有一些优秀的组件可以执行SMTP验证之外的多个级别的验证。例如,首先检查是否至少存在该域是值得的。我正在编制与此问题相关的我自己的资源列表,您可以在此处跟踪: (断开的链接) 对于那些可能想添加到此列表的人,我还将在此处包括我目前拥有的内容:
- 语法
- 根据错误电子邮件地址列表删除电子邮件
- 根据坏域列表创建域
- 邮箱域的列表
- 域是否存在
- 域是否有MX记录
- 最后通过SMTP检查邮箱是否存在
// 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);
}
您可以尝试下面的代码,它对我来说很好:
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;
}
}
公共类电子邮件测试{
私有静态int-hear(BufferedReader-in)引发IOException{
字符串行=null;
int res=0;
而((line=in.readLine())!=null){
字符串pfx=行。子字符串(0,3);
试一试{
res=整数.parseInt(pfx);
}捕获(例外情况除外){
res=-1;
}
如果(第3行字符)!='-')
打破
}
返回res;
}
私有静态void say(BufferedWriter wr,字符串文本)引发IOException{
wr.write(text+“\r\n”);
wr.flush();
返回;
}
@SuppressWarnings({“rawtypes”,“unchecked”})
私有静态ArrayList getMX(字符串主机名)引发NamingException{
//对域中的MX记录执行DNS查找
Hashtable env=新的Hashtable();
put(“java.naming.factory.initial”、“com.sun.jndi.dns.DnsContextFactory”);
DirContext ictx=新的初始DirContext(env);
Attributes attrs=ictx.getAttributes(主机名,新字符串[]{“MX”});
属性attr=attrs.get(“MX”);
//如果我们没有MX记录,请尝试机器本身
如果
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;
}
}