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.
Related
I am sending emails via exchange web services (EWS C#), modern authentication and Exchange Online.
This works fine for all email addresses tested except one. This one email address is the main SMTP address of a user in our organization.
When I try to send the email it results in an error
"Microsoft.Exchange.WebServices.Data.ServiceResponseException: At least one recipient is not valid., Recipient 'xxxx.xxxx#yyy.com ' is not resolved. All recipients must be resolved before a message can be submitted."
The mail then resides in the draft folder of the sending mailbox.
If I view it there with Outlook then it shows 2-3 seconds the entered SMTP email address of the user and then it switches to this underlined resolved name view in Outlook.
Is there a way in EWS to trigger this resolve process manually? Or do I need a setting on the server?
Or am I missing something?
Thanks.
This is my code:
log.Debug("create email object");
EmailMessage message = new EmailMessage(service);
// Set properties on the email message.
message.Subject = subject;
message.Body = body;
message.From = from;
foreach (string emailReplyTo in replyTo)
{
message.ReplyTo.Add(emailReplyTo);
}
foreach (string emailTo in recipients)
{
message.ToRecipients.Add(emailTo);
}
if (cc != null)
{
foreach (string emailTo in cc)
{
message.CcRecipients.Add(emailTo);
}
}
if (bcc != null)
{
foreach (string emailTo in bcc)
{
message.BccRecipients.Add(emailTo);
}
}
if (attachmentData != null && !String.IsNullOrWhiteSpace(attachmentFileName))
{
log.Debug("Add attachment");
message.Attachments.AddFileAttachment(attachmentFileName, attachmentData);
}
log.Debug("Send and save copy of email");
message.SendAndSaveCopy();
log.Debug("Successfully sent email");
return true;
Funny thing. The issue was that the email address had a trailing blank.
The Exchange server is still able to resolve when viewing it in Outlook (it just takes some seconds) but in the code it creates the issue.
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
I am trying to get the email address of a particular user in TFS 2012 using the API. I have set the users Preferred Email address in the Profile section. I have done plenty of searching online and have the following code.
var userId = "myUserId";
var collection = new TfsTeamProjectCollection(tfsUri, tfsCerd);
var managementService = collection.GetService<IIdentityManagementService>();
var member =
managementService
.ReadIdentity(
IdentitySearchFactor.AccountName,
userId,
MembershipQuery.Direct,
ReadIdentityOptions.ExtendedProperties);
var emailAddress = member.GetAttribute("Mail", null)
This code is both a success and a failure. It is a success in that it successfully retrieves the specified user; however, the problem is that the Email attribute is blank. When I analyzed the member variable, I noticed the "Mail" attribute was listed there and it was empty. I then noticed there were two other attributes called "ConfirmedNotificationAddress" and "CustomNotificationAddress" that had my preferred email address correctly in there.
I am wondering why I can't seem to get the "Mail" variable to load properly with the preferred email address as I will need this code to work on a lot of peoples servers.
Try using Mail instead of Email for the attribute name - that works for me.
Also, if that doesn't work, check the results of member.GetProperties() - maybe that will give you the right name to use.
For me, GetProperty("Mail") also worked.
I bumped into the same problem, I found a work around by getting my users email address from AD using the following code.
public string GetUserEmail(string username)
{
using (var pctx = new PrincipalContext(ContextType.Domain))
{
using (UserPrincipal up = UserPrincipal.FindByIdentity(pctx, username))
{
return up != null && !string.IsNullOrEmpty(up.EmailAddress) ? up.EmailAddress : string.Empty;
}
}
}
But then I found that it would throw an exception when my user was not in my domain. So this code helped me have an a second source. If I didn't find in AD i would go and use the IdentityManagementService.
public TeamFoundationIdentity GetUserByAccountName(string account)
{
var ims = _tfServer.GetService<IIdentityManagementService>();
return ims.ReadIdentity(IdentitySearchFactor.DisplayName, account, MembershipQuery.Expanded, ReadIdentityOptions.ExtendedProperties);
}
Then I would simply use this execution.
var ownerMail = GetUserEmail(checkinEvent.Resource.CheckedInBy.DisplayName);
if (string.IsNullOrEmpty(ownerMail))
{
ownerMail = GetUserByAccountName(checkinEvent.Resource.CheckedInBy.DisplayName).GetProperty("Mail").ToString();
}
Using the Exchange Web Services API, is it possible to determine whether a mailbox/e-mail address such as someone#mydomain.com exists within an organization?
If so, which is the simplest way to do this and is it possible without the use of impersonation?
Case: A Windows Service regularly sends e-mails to people within the organization. It does not have any explicit knowledge about their e-mail adresses. It only knows their username and assumes that their e-mail address is username#mydomain.com. This is true for all users except for a few that do not have mailboxes. In these cases, it should not attempt to send the e-mail in the first place.
Solution:
As suggested by mathieu: look for user and e-mail address in Active Directory instead. This function gets the job done:
using System.DirectoryServices.AccountManagement;
// ...
public static bool TryGetUserEmailAddress(string userName, out string email)
{
using (PrincipalContext domainContext =
new PrincipalContext(ContextType.Domain, Environment.UserDomainName))
using (UserPrincipal user =
UserPrincipal.FindByIdentity(domainContext, userName))
{
if (user != null && !string.IsNullOrWhiteSpace(user.EmailAddress))
{
email = user.EmailAddress;
return true;
}
}
email = null;
return false; // user not found or no e-mail address specified
}
Determining if an user has a mailbox with EWS only could be more complicated than expected, especially without impersonation.
If you're in an Active Directory domain, you should rely on the DirectoryEntry information to determine the mailbox of an user, and send email accordingly. If you got your user login, it's really easy to get the associated DirectoryEntry.
there is an easy way to do it by checking the user availability like the following code.
I tried this and it is working for me.
I am not sure about other cases when availability result returns error but for sure when the email is not right it does
to define your exchange service refer to this: https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/get-started-with-ews-managed-api-client-applications
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);//You version
service.Credentials = new WebCredentials("user1#contoso.com", "password");
service.AutodiscoverUrl("user1#contoso.com", RedirectionUrlValidationCallback);
string email = "TEST#YOUR.COM";
// Get User Availability after 6 months
AttendeeInfo attendee = new AttendeeInfo(email);
var attnds = new List<AttendeeInfo>();
attnds.Add(attendee);
var freeTime = service.GetUserAvailability(attnds, new
TimeWindow(DateTime.Now.AddMonths(6), DateTime.Now.AddMonths(6).AddDays(1)), AvailabilityData.FreeBusyAndSuggestions);
//if you receive result with error then there is a big possibility that the email is not right
if(freetimes.AttendeesAvailability.OverallResult == ServiceResult.Error)
{
return false;
}
return true;
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;
}
}
}