Email SMTP validator - validation

I need to send hundreds of newsletters, but would like to check first if email exists on server. It's called SMTP validation, at least I think so, based on my research on Internet.
There's several libraries that can do that, and also a page with open-source code in ASP Classic (http://www.coveryourasp.com/ValidateEmail.asp#Result3), but I have hard time reading ASP Classic, and it seems that it uses some third-party library...
Is there some code for SMTP validation in C#, and/or general explanation of how it works?

Be aware that most MTAs (Mail Transfer Agent) will have the VRFY command turned off for spam protection reasons, they'll probably even block you if you try several RCPT TO in a row (see http://www.spamresource.com/2007/01/whatever-happened-to-vrfy.html). So even if you find a library to do that verification, it won't be worth a lot. Ishmaeel is right, the only way to really find out, is sending an email and see if it bounces or not.
#Hrvoje: Yes, I'm suggesting you monitor rejected emails. BUT: not all the bounced mails should automatically end up on your "does not exist"-list, you also have to differentiate between temporary (e.g. mailbox full) and permanent errors.

SMTP is a text based protocol carried over TCP/IP.
Your validation program needs to open a TCP/IP connection to the server's port 25 (SMTP), write in a few lines and read the answer. Validation is done (but not always) on the "RCTP TO" line and on the "VFRY" line.
The SMTP RFC describes how this works (see Green#Beta.ARPA below, S are lines sent by the client, R are lines received from the server):
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

While it's true that many domains will return false positives because of abuse, there are still some great components out there that will perform several levels of validation beyond just the SMTP validation. For example, it's worth it to check first to see if at least the domain exists. I'm in the process of compiling my own list of resources related to this question which you can track here:
http://delicious.com/dworthley/email.validation (broken link)
For those who might want to add to this list, I'll also include what I currently have here:
aspNetMX
.NET Email Validation Wizard Class Library
MONOProg Email Validator.Net
For a bulletproof form and a great user experience, it's helpful to validate as many aspects of the email address as possible. I can see from the aspNetMX validator that they check:
the syntax
the email against a list of bad email addresses
the domain against a list of bad domains
a list of mailbox domains
whether or not the domain exists
whether there are MX records for the domain
and finally through SMTP whether or not a mailbox exists
It's this last step that can be circumvented by administrators by returning true to basically all account verification requests, but in most cases if the user has intentionally entered a bad address it's already been caught. And if it was user error in the domain part of the address, that will be caught too.
Of course, a best practice for using this kind of a service for a registration screen or form would be to combine this kind of validation with a verification process to ensure that the email address is valid. The great thing about using an email validator in front of a verification process is that it will make for a better overall user experience.

You can try the below code, it works fine for me :
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;
}
}
Thanks & Regards
Rahul Saraswat

The Real(TM) e-mail validation is trying to send something to the address, and seeing if it is rejected/bounced. So, you'll just have to send them away, and remove the addresses that fail from your mailing list.

Don't take this the wrong way, but sending newsletters to more than a handful of people these days is a fairly serious matter. Yes, you need to be monitoring bounces (rejected emails) which can occur synchronously during the SMTP send (typically if the SMTP server you are connected to is authoritative), or asynchronously as a system-generated email message that occurs some amount of time after the SMTP send succeeded.
Also keep the CAN-SPAM Act in mind and abide by the law when sending these emails; you've got to provide an unsub link as well as a physical street address (to both identify you and t0 allow users to send unsub requests via snail-mail if they so choose).
Failure to do these things could get your IP null-routed at best and sued at worst.

You may need this Email Validator component for .NET
Here is the code example:
// 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);
}

Related

Discord JDA can't get getMutualGuilds() to work

Im trying to make a bot that sends a pm when someone joins a server, and then assigns a role based on reply to said Pm.
This is the following code i have so far for onMessageRecieved, issue is that user.getMutualGuilds() returns an empty list even though they are part of the same server as the bot.
#Override
public void onMessageReceived(MessageReceivedEvent event) {
String DmRecieved = event.getMessage().getContentRaw();
User user = event.getAuthor();
boolean isBot = user.isBot();
boolean startsWithAU = DmRecieved.toUpperCase().startsWith("AU", 0);
boolean messageTooLong = DmRecieved.length() > 8;
if (event.getMessage().getContentRaw().isEmpty()) return;
if (isBot) return;
if (!startsWithAU || messageTooLong) {
user.openPrivateChannel().queue((chanel1 ->
chanel1.sendMessage("Not valid AU ID, please try again.").queue()));
} else {
List<Guild> guilds = user.getMutualGuilds();
System.out.println(guilds);
}
}
I found the fix. The members needed to be cached in memory this was done by adding the following line to the JDA:
jda.setMemberCachePolicy(member -> true);

Smack : Is it possible to get the message composed by the user as he writes it in a chat?

We have a chat application which is using Smack, XMPP, ejabberd. I'm wondering if it's possible to achieve something like below:
A chat is open between 2 users.
User1 is typing some message.
User2 is able to see the message typed by User1 as he types it.
I have done a bit of research but couldn't find anything related.
Please let me know how to achieve this use case.
Thanks in advance!
That is not possible. You can send the text as user types but each piece will go as independent message. If you want that one you might want to have your own way to do so. XMPP have no way to do so!
With Smack it is easy, whenever the user changes the text you send a typing stanza to the other person using the ChatStateExtension:
private void sendTypingStatus(final String toJid) {
//you must have a valid xmpp connection of course
if (null == mConnection)
return;
try {
Message message = new Message(JidCreate.from(toJid));
message.addExtension(new ChatStateExtension(ChatState.composing));
message.setType(Message.Type.chat);
mConnection.sendStanza(message);
} catch (InterruptedException | SmackException.NotConnectedException | XmppStringprepException ex) {
Log.w(TAG, "sendTypingStatus error", ex);
}
}
The other person should be prepared to receive the stanza and use it correctly. The best option is to use ChatStatesStanzaListener for that:
public class ChatStatesStanzaListener implements StanzaListener {
private static final String TAG = ChatStatesStanzaListener.class.getSimpleName();
#Override
public void processStanza(Stanza packet) {
Message message = (Message) packet;
if (message.hasExtension(ChatStateExtension.NAMESPACE)) {
ChatStateExtension chatStateExtension = (ChatStateExtension) message.getExtension(ChatStateExtension.NAMESPACE);
ChatState chatState = chatStateExtension.getChatState();
String fromJid = message.getFrom().asBareJid().toString();
if (message.getType().equals(Message.Type.chat)) {
Log.v(TAG, "got chat state " + fromJid + " " + message.getType() + " " + chatState);
//you got youe information here, call a callback or broadcast an event, whatever
} else if (message.getType().equals(Message.Type.groupchat)) {
//out of your question
}
}
}
}
Don't forget to add the stanza listener to your xmpp connection once it's established:
1. Set the stanza filter:
// set up a stanzalistener and filter chatstates messages only
StanzaFilter chatStatesStanzaFilter = stanza -> {
// filter for chatstates message only
return stanza.hasExtension(ChatStateExtension.NAMESPACE);
};
Use it once you initialize the xmpp connection:
mConnection.addAsyncStanzaListener(new ChatStatesStanzaListener(), chatStatesStanzaFilter);
I hope it helps :)

I want to send mail to custom domain email provider in windows mobile application

I want to send mail from my windows mobile application.
I have configured new mail account on windows mobile emulator 6.5.3. with custom domain email provider,
Now I am able to send and receive mails with that device,And I want to send mail from my code,when the button is clicked
A code to send mail by code is available here: Sending mail in Windows mobile application in Windows
If you need more assistance, please provide more details.
EDIT: to make it more clear:
First you have to create an outlook session and specify the account to use:
public sendMail(string sMailAccount)
{
session = new OutlookSession();
//eMail = new EmailMessage();
bool bFound = false;
foreach (Account acc in session.EmailAccounts)
{
System.Diagnostics.Debug.WriteLine(acc.Name);
if (acc.Name == sMailAccount)
bFound = true;
}
if (bFound)
account = session.EmailAccounts[sMailAccount];
if (account != null)
...
The above starts a seesion and uses the provided string sMailsAccount to find an existing defined mail account. The string has to match any of the mail accounts you already have ceĀ“reated in pocket outlook.
Then, when you want to send an eMail, you use the existing session:
public bool send(string sImagePath)
{
if (account == null)
return false;
try
{
eMail = new EmailMessage();
rcp = new Recipient(_to);
eMail.To.Add(rcp);
eMail.Subject = "Visitenkarten";
eMail.BodyText = "VCard " + DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString() + "\r\nsent from eMDI2Mail";
attachement = new Attachment(sImagePath);
eMail.Attachments.Add(attachement);
eMail.Send(account);
//account.Send(eMail);
if (this._syncImmediately)
{
if (this.account != null)
Microsoft.WindowsMobile.PocketOutlook.MessagingApplication.Synchronize(this.account);
}
return true;
}
...
The above code creates a new eMail, attaches a file and sends the eMail immediately or lets outlook decide, wehn to send (at a specified interval). The eMail is send immediately, if Synchronize function is used.
Makes it more clear?

Reply To Email Address Not Working

I am trying to send an email address in my application as someone (email should show up as if it were sent from that), but anytime I send the email, the name shows up as I supplied, but no matter what I do, the email address is what I am using to authenticate.
Is there any way to have the email to appear as if it is coming from someone I specify or will it always show up as coming from the authenticated email?
Here is what I have...
using (var message = new MailMessage()
{
From = From != new MailAddress(From.Email, From.FormalName),
Subject = Subject,
Body = Body
})
{
if (To != null)
{
foreach (var address in To)
{
message.To.Add(new MailAddress(address.Email, address.FormalName));
}
}
if (CC != null)
{
foreach (var address in CC)
{
message.CC.Add(new MailAddress(address.Email, address.FormalName));
}
}
var smtp = new SmtpClient
{
Host = "smtp.gmail.com",
Port = 587,
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NetworkCredential("myaccount", "mypassword")
};
message.IsBodyHtml = true;
message.Headers.Add("Reply-To", message.From.Address);
smtp.Send(message);
}
It looks like you're expecting the Reply-To: header to indicate who the message is from. In fact, there is a header called From: for this purpose. So try:
message.Headers.Add("From", message.From.Address);
Do note that Gmail will probably add a Sender: header (that may or may not be shown by the recipient's email client) that reflects the actual account you used to send the message.
Best practice when sending automated emails from a specific user is to use the 'on behalf of' syntax (ReplyTo or Sender in MailMessage) in conjunction with a from address from your system see Sending "on behalf of" emails
however you can put the address straight into from as a string so long as your mail server supports it and the receiving mail server does not do a reverse look-up

FTP status code response don't work

Welcome!
I have a little problem with own application. This app can be connect(sith socket) an FTP server, and its work fine. But my problem is, if the user use bad usernam or password, the program won't receive the response statucode. Whats wrong?
I would like to use this statuscode some clause to examine(usernem or/and password etc.)
Code:
public static void ReadResponse()
{
result = ParseHostResponse();
statusCode = int.Parse(result.Substring(0, 3));
statusMessage = "";
}
The ParseHostResponse() method contains next:
Code:
public static string ParseHostResponse()
{
SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
socketEventArg.RemoteEndPoint = socket.RemoteEndPoint;
socketEventArg.SetBuffer(buffer, BUFFER_SIZE, 0);
socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
statusMessage = Encoding.UTF8.GetString(e.Buffer, e.Offset, e.BytesTransferred);
statusMessage = statusMessage.Trim('\0');
}
else
{
statusMessage = e.SocketError.ToString();
}
});
socket.ReceiveAsync(socketEventArg);
string[] msg = statusMessage.Split('\n');
if (statusMessage.Length > 2)
{
statusMessage = msg[msg.Length - 2];
}
else
{
statusMessage = msg[0];
}
if (!statusMessage.Substring(3, 1).Equals(" "))
{
return ParseHostResponse();
}
return statusMessage;
}
If I invite to the ReadResponse() method, the Visual Studio answer with this exception: NullReferenceException
in this code:
Code:
.
.
string[] msg = statusMessage.Split('\n');
.
What is the wrong? This code issue to http://msdn.microsoft.com/en-us/library/hh202858%28v=vs.92%29.aspx#BKMK_RECEIVING
Thank you for your help!
I can't help, but have to start with these side remarks:
statusMessage.Trim('\0') does not work (try it)
statusMessage.Split('\n') is inefficient as it involves extra allocations (guess why)
Now to the actual subject: I never used sockets on WP7, but from what I know about async operations it looks to me that you start async op (by calling ReceiveAsync) and use the result (statusMessage) before the answer arrives.
Think a bit about your design of the ParseHostResponse() method:
Bad name: Indicates parsing of a response, while it actually performs communication
Bad functionality: The method indicates sync patter, but internally uses async pattern. I don't know what to suggest here as every solution seems to be wrong. For example waiting for a response will make UI irresposible.
My main recommendation is that you get more information about async programming and then reprogramm your app accordingly.

Resources