Is there any easy/elegant way to verify, that a SMTP address is associated with an Exchange mailbox via EWS?
Credentials of an administrative Exchange user are given.
The following quick and dirty solution works:
Create an ExchangeService with the SMTP address as Impersonated user
Try to make a method call
When the exception message is "The SMTP address has no mailbox associated with it.", the SMTP address is not associated with a mailbox
Problem:
Not that elegant to compare the exception message
Takes about 200-250ms per user (not parallel)
Another Problem:
It is possible, that there are contacts in the GAL, that don't have a mailbox.
So ResolveNames won't be helpful.
The easiest way is to use the ResolveName operation and search the Directory you just need to prefix the address with smtp: and Exchange will the search both the Primary and proxyaddressses eg
String EmailAddresstoCheck = "info#domain.com";
NameResolutionCollection ncCol = service.ResolveName(("SMTP:" + EmailAddresstoCheck), ResolveNameSearchLocation.DirectoryOnly, true);
if (ncCol.Count == 1)
{
if (ncCol[0].Contact != null)
{
if (EmailAddresstoCheck.ToLower() == ncCol[0].Mailbox.Address)
{
Console.WriteLine("Primary SMTP Address of " + ncCol[0].Contact.DisplayName);
}
else
{
Console.WriteLine("Proxy Address of " + ncCol[0].Contact.DisplayName);
Console.WriteLine("Primary SMTP Address : " + ncCol[0].Mailbox.Address);
}
}
}
Cheers
Glen
Related
My client has a problem and it mean I have a problem:
In the case where email recipient have multiple emails configured in Outlook -
I have one yahoo email account and 2 Exchange accounts from different Exchange servers.
When processing incoming email in ProcessItemAdd event handler (Add-In Express)
I try to discover what account out of 3 this email was sent to:
So my first method is:
Outlook.MailItem re = ((Outlook._MailItem)mail).Reply();
if (re != null)
{
var thisEmail = "";
Outlook.Account account = re.SendUsingAccount;
if (account != null)
{
thisEmail = account.SmtpAddress;
Log.VerboseFormat("thisEmail = {0}", thisEmail);
Marshal.ReleaseComObject(re);
re = null;
Marshal.ReleaseComObject(account);
account = null;
It works perfectly on my machine with Outlook 2010 32bit, but does not work on my client machine with Outlook 2010, returning empty string.
So my second (backup method) is:
if (String.IsNullOrEmpty(thisEmail))
{
// This requires that in the case of Exchange account it should be cached Exchange account.
thisEmail = (string)mail.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/id/{00062008-0000-0000-C000-000000000046}/8580001F");
Log.VerboseFormat("Got receiver account email address from schema: {0}", thisEmail);
}
}
}
Again this works perfectly on my machine but does not work on client machine, returning empty string.
I did verify that in my client's case the sender is Exchange account with caching...
BTW, it works fine on client machines when sender is non-Exchange and receiver is Exchange account...
Is there any other method that reliably can determine what account the email was sent to (in case of multiple recipients).
Here is my latest code that works on 2010/2013 but not on 2007. On the latter account is null and x-header returned empty:
Outlook.MailItem re = ((Outlook._MailItem)mail).Reply();
if (re != null)
{
var thisEmail = "";
Outlook.Account account = re.SendUsingAccount;
if (account != null)
{
thisEmail = account.SmtpAddress;
Log.VerboseFormat("thisEmail = {0}", thisEmail);
Marshal.ReleaseComObject(re);
re = null;
Marshal.ReleaseComObject(account);
account = null;
if (String.IsNullOrEmpty(thisEmail))
{
string x_headers = (string)mail.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x007D001F");
thisEmail = FindTargetEmail(x_headers);
Log.Verbose("Extracted target email address from MIME x-headers: {0}", thisEmail);
}
}
else
{
Log.Verbose("account is null...");
if (String.IsNullOrEmpty(thisEmail))
{
string x_headers = (string)mail.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x007D001F");
thisEmail = FindTargetEmail(x_headers);
Log.Verbose("Extracted target email address from MIME x-headers: {0}", thisEmail);
}
}
EDIT:
Well, it is not over yet. Although it works well on all machines that I have client reports a problem on 2010. It is very strange problem.
User user1#domain1.com (cached Exchange account) sends email to user user2#domain2.com (gmail account). When I parse the MIME header on the receiver side with the above code in order to get the address that this email was sent to...I get back user1#domain1.com instead of user2#domain2.com !! How this is possible? I know that I am parsing the right part of the header (do I ?) and on my machines it returns the correct result...why it does not happen on SOME of my client's machines??
Experts, any ideas?
Typically a Store in the Outlook profile represents a separate account. You may handle the ItemAdd event of the Items class (ProcessItemAdd in ADX terms) in each store to identify the account the email message was sent to.
Our application sends out emails using the
new SmtpClient(smtpServer).Send(message);
We are making sure that the smtpServer is valid, the message has To and From addresses, a subject and a body. If any of these are missing, we would log an exception before even attempting to send a message.
But the application frequently fails with the below exception.
Email Fail: System.Net.Mail.SmtpException: Mailbox unavailable. The server response was: Too many invalid recipients.
Now, please note that the email send functionality is not failing always. For the same "To" address, it fails, may be about half the times. So, if the application tries sending out emails 100 times, we are getting some 40+ failures with the same message.
I have already validated that the To address and the From address exists. We are seeing this issue since last month when we shifted from Outlook to Gmail.
Here is the code.
if (fromAddress.Length == 0)
fromAddress = Resources.FromAddress;
if (toAddress.Length == 0) return "To Address is Required.";
if (smtpServer.Length == 0)
smtpServer = Resources.SMTPServer;
if (string.IsNullOrEmpty(smtpServer))
return "SMTP sever not specified";
MailMessage mailMessage = new MailMessage();
//set the addresses
mailMessage.From = new MailAddress(fromAddress);
string[] toAdds = toAddress.Split(';');
short i = 0;
foreach (string address in toAdds)
{
if(i==0) mailMessage.To.Add(address); else mailMessage.CC.Add(address);
i++;
}
if (!string.IsNullOrEmpty(bcc))
{
string[] bccAddresses = bcc.Split(';');
foreach (string address in bccAddresses)
{
mailMessage.Bcc.Add(address);
}
}
if (!string.IsNullOrEmpty(cc))
{
string[] ccAddresses = cc.Split(';');
foreach (string address in ccAddresses)
{
mailMessage.CC.Add(address);
}
}
if (subject.Length > 0)
mailMessage.Subject = subject;
mailMessage.Body = sBody;
mailMessage.IsBodyHtml = true;
SmtpClient emailClient = new SmtpClient(smtpServer);
emailClient.Send(mailMessage);
Any directions?
If the same email with the same sender and recipients is sometimes accepted, sometimes rejected by the SMTP server, it may be the result of a server antispam policy. For example :
Directory Harvest Attack Prevention (DHAP) : which causes a "550 Too many invalid recipients" error when exceeding a number of RCPT TO commands over a given period of time.
Quotas : a limit on the number of mails that a mailbox/IP can send per minute/second to prevent spamming.
You can validate if the SMTP server settings are the cause of your problem by (temporarily) :
whitelisting the IP address of your SMTP client
disabling any quota/antispam Policy applied to your sender's mailbox
If that doesn't solve your problem, then use a tool like WireShark to record the SMTP dialog and check exactly what email addresses are sent in the RCPT TO command, and in which cases the SMTP Server rejects them. Then, post it here.
I have the below snippet from my authentication login page
How can I modify it so that it takes the Primary SMTP mail address from AD? Currently it appears that it takes the first one that it finds.
Is there a property to only get the primary mail address?
adsSearcher.Filter = "(sAMAccountName=" + strAccountId + ")";
adsSearcher.PropertiesToLoad.Add("mail");
try
{
SearchResult adsSearchResult = adsSearcher.FindOne();
bool bSucceeded = true;
string strAuthenticatedBy = "Active Directory";
string strError = "User has been authenticated by Active Directory.";
adsEntry.Close();
try
{
if (adsSearchResult.Properties["mail"] != null && adsSearchResult.Properties["mail"].Count > 0)
{
Session["email"] = adsSearchResult.Properties["mail"][0].ToString().ToLower();
}
The best way to do this is actually to retrieve the proxyAddresses attribute. Each entry in that attribute is prefixed with a protocol (e.g. SIP:, SMTP:, etc.). The proxy with the capitalized prefix (e.g. SMTP: vs smtp:) is the primary address for that protocol. The mail attribute /should/ be in sync but it's not always the case.
I get this error when I try to send an e-mail to a specific address in my code:
System.Net.Mail.SmtpFailedRecipientException: Mailbox unavailable. The server response was: Unknown user
The code sends an e-mail to two email addresses, mine and my colleague's. The e-mail sends to me just fine, but I get that error when it tries to send the email to him.
I looked around, and basically the common explanation for this error is that the email address is invalid, or their mailbox is full and isn't allowed to receive mail, or there is some setting on the server that is restricting it from receiving an e-mail.
But the email address is able to receive email, I'm corresponding back and forth through e-mail with him right now.
Is there any other reason why this error might occur?
EDIT:
Here's the code, maybe someone can spot an issue. I checked the parameters being passed, all the data is correct:
private static void SendEmail(IEnumerable<MailAddress> to, MailAddress from,
string subject, string body, string bodyHtml)
{
var mail = new MailMessage { From = from, Subject = subject };
foreach (var address in to)
{
mail.To.Add(address);
}
mail.AlternateViews.Add(
AlternateView.CreateAlternateViewFromString(bodyHtml, null, "text/html"));
mail.AlternateViews.Add(
AlternateView.CreateAlternateViewFromString(body, null, "text/plain"));
try
{
var smtp = new SmtpClient("localhost", 25)
{
Credentials = new NetworkCredential("xxx", "xxx")
};
smtp.Send(mail);
}
catch (Exception err)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(err);
}
}
Assuming your SMTP settings are correct this is most probably a case of a server-side restriction...
For example to prevent spam the server only accepts smtp from static sender IP and/or is checking sender IP against MX records (DNS) etc.
I have done this before without any issue but now I don't know what's wrong. I have a web page with a button for email which I want to send some data to email addresses with.
I asked our web hosting company for server details and the response I got was:
"You can use the following details for mail.
Incoming mail server: mail.ourSite.com Outgoing mail server: mail.ourSite.com
Username and password are the email address and password associated with the email address.
"
I am not sure about the last line but I created a new email address in the web host's control panel.
The code I use is:
// instantiate a new mail definition and load an html
// template into a string which I replace values in
// then the rest of the code below
md.Subject = String.Format("{0} {1} {2}", emailSubject, firstName, lastName);
MailMessage msg = md.CreateMailMessage(emailAddress, replacements, emailBody, new Control());
md.IsBodyHtml = true;
SmtpClient sc = new SmtpClient(emailServer);
sc.Credentials = new NetworkCredential(emailUsername, emailPassword);
try
{
sc.Send(msg);
}
emailServer - mail.ourSite.com (dummy value in this post)
emailUsername - the email address I created in the control panel
emailPassword - the password for the email above
The error I have is that when I send emails to other domains than our own I get
"Bad sequence of commands. The server response was: This mail server requires authentication when attempting to send to a non-local e-mail address. Please check your mail client settings or contact your administrator to verify that the domain or address is defined for this server."
When I email to an address within our host then it works fine.
The support is not very supportive so I am asking here what you might think the problem could be? I find it strange that I use the password for an email address I created, should it really be like that?
I think that you are using the wrong email address for the NetworkCredential. It should be the one for your email account that you got from the one providing emailServer.
Try this ..
msg.UseDefaultCredentials = false;
NetworkCredential MyCredential = new NetworkCredential("Email", "Password");
msg.Credentials = MyCredential;
here is code to send mail..
i hope i will helpful to you..
using System.Web.Mail;
using System;
public class MailSender
{
public static bool SendEmail(
string pGmailEmail,
string pGmailPassword,
string pTo,
string pSubject,
string pBody,
System.Web.Mail.MailFormat pFormat,
string pAttachmentPath)
{
try
{
System.Web.Mail.MailMessage myMail = new System.Web.Mail.MailMessage();
myMail.Fields.Add
("http://schemas.microsoft.com/cdo/configuration/smtpserver",
"smtp.gmail.com");
myMail.Fields.Add
("http://schemas.microsoft.com/cdo/configuration/smtpserverport",
"465");
myMail.Fields.Add
("http://schemas.microsoft.com/cdo/configuration/sendusing",
"2");
//sendusing: cdoSendUsingPort, value 2, for sending the message using
//the network.
//smtpauthenticate: Specifies the mechanism used when authenticating
//to an SMTP
//service over the network. Possible values are:
//- cdoAnonymous, value 0. Do not authenticate.
//- cdoBasic, value 1. Use basic clear-text authentication.
//When using this option you have to provide the user name and password
//through the sendusername and sendpassword fields.
//- cdoNTLM, value 2. The current process security context is used to
// authenticate with the service.
myMail.Fields.Add
("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate","1");
//Use 0 for anonymous
myMail.Fields.Add
("http://schemas.microsoft.com/cdo/configuration/sendusername",
pGmailEmail);
myMail.Fields.Add
("http://schemas.microsoft.com/cdo/configuration/sendpassword",
pGmailPassword);
myMail.Fields.Add
("http://schemas.microsoft.com/cdo/configuration/smtpusessl",
"true");
myMail.From = pGmailEmail;
myMail.To = pTo;
myMail.Subject = pSubject;
myMail.BodyFormat = pFormat;
myMail.Body = pBody;
if (pAttachmentPath.Trim() != "")
{
MailAttachment MyAttachment =
new MailAttachment(pAttachmentPath);
myMail.Attachments.Add(MyAttachment);
myMail.Priority = System.Web.Mail.MailPriority.High;
}
System.Web.Mail.SmtpMail.SmtpServer = "smtp.gmail.com:465";
System.Web.Mail.SmtpMail.Send(myMail);
return true;
}
catch (Exception ex)
{
throw;
}
}
}