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.
Related
I'm simply trying to use the Office 365 API to send an email via the "Send()" function, but am getting back Microsoft.Exchange.Webservices.Data.ServiceResponseException: Mailbox does not exist.
Here's my exchange service:
_emailExchangeService =
new ExchangeService(ExchangeVersion.Exchange2013_SP1)
{
Url = new Uri(_settings.ExchangeWebServiceEndpoint),
Credentials = new WebCredentials(_settings.AppEmailUserName, _settings.AppEmailPassword),
TraceEnabled = true,
UseDefaultCredentials = false
};
And here's the code I'm using to send the email:
public void SendEmail(MemoryStream attachment, string body, string subject, string recipients, string fromMailbox)
{
EmailMessage message = new EmailMessage(_emailExchangeService);
message.From = fromMailbox;
message.Subject = subject;
message.Body = new MessageBody(BodyType.Text, body);
message.ToRecipients.Add(recipients);
message.Attachments.AddFileAttachment("FileName", attachment);
message.Send();
}
What mailbox am I forgetting to define when sending this, the sent box? I thought the "from" field would define the mailbox for sending items. I'm just not even sure where to do that and my code looks identical to the docs.
Side note: I know the exchange service is set up correctly because if I define an inbox email address and attempt to FindItems(_inbox) on the mailbox, it works.
I have a service running as a scheduled job on a machine. It's running under a service account that doesn't have it's own mailbox. We would like it to send emails from the team's shared inbox.
Using impersonation here is what I tried.
var service = new ExchangeService
{
TraceEnabled = true,
ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, Resources.EmailUsername)
};
service.AutodiscoverUrl(Resources.EmailUsername, RedirectionUrlValidationCallback);
var email = new EmailMessage(service);
if (!string.IsNullOrWhiteSpace(recipients))
{
foreach (var recipient in recipients.Split(','))
{
email.ToRecipients.Add(recipient.Trim());
}
}
email.Subject = subject;
email.Body = new MessageBody(BodyType.HTML, body);
if (attachmentName != null && attachment != null)
{
email.Attachments.AddFileAttachment(attachmentName, attachment);
}
email.Send();
It fails and I get an exception saying:
When making a request as an account that does not have a mailbox, you
must specify the mailbox primary smtp address for any distinguished
folder Ids.
The TraceEnabled part led me to notice MessageDisposition=SaveOnly was set in the xml. I looked up MessageDisposition and figured I wanted SendOnly.
After much searching I ended up here: https://github.com/OfficeDev/ews-managed-api/blob/master/Core/ServiceObjects/Items/EmailMessage.cs
Which shows:
public void Send()
{
this.InternalSend(null, MessageDisposition.SendOnly);
}
Well that looks like what I wanted in the first place... But then:
private void InternalSend(FolderId parentFolderId, MessageDisposition messageDisposition)
{
this.ThrowIfThisIsAttachment();
if (this.IsNew)
{
if ((this.Attachments.Count == 0) || (messageDisposition == MessageDisposition.SaveOnly))
{
this.InternalCreate(
parentFolderId,
messageDisposition,
null);
}
else
{
// If the message has attachments, save as a draft (and add attachments) before sending.
this.InternalCreate(
null, // null means use the Drafts folder in the mailbox of the authenticated user.
MessageDisposition.SaveOnly,
null);
this.Service.SendItem(this, parentFolderId);
}
}
...
The two comments are the most enlightening parts. The attachment is being saved to the drafts folder of the user running the process.
To get around this, the message must already be saved when we call Send. Let's make sure it is saved in the mailbox we know exists. So we remove the impersonation, add a step to save it, and modify the From field. Then we can safely send the message, and it will remove itself from the draft folder.
var service = new ExchangeService
{
TraceEnabled = true
};
service.AutodiscoverUrl(Resources.EmailUsername, RedirectionUrlValidationCallback);
var email = new EmailMessage(service);
if (!string.IsNullOrWhiteSpace(recipients))
{
foreach (var recipient in recipients.Split(','))
{
email.ToRecipients.Add(recipient.Trim());
}
}
email.Subject = subject;
email.Body = new MessageBody(BodyType.HTML, body);
if (attachmentName != null && attachment != null)
{
email.Attachments.AddFileAttachment(attachmentName, attachment);
}
var folderId = new FolderId(WellKnownFolderName.SentItems, Resources.EmailUsername);
email.Save(folderId);
email.From = Resources.EmailUsername;
email.Send();
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.
We use the excellent AuthSMTP service for outgoing mail from our MVC application. Until we upgraded to .Net 4.5.1 we used SmtpMail.SendAsync to send out multiple emails at once via IIS7. IIS7 is set to relay mail through AuthSMTP.
These days asynchronous code in .Net seems to work differently. We rolled back to SmtpMail.Send which has slowed the site down where multiple mails are sent. We are considering the following options.
Rewrite the code to work with the Task-based Asynchronous Pattern. We're fairly confused by this but could persevere if it's a good option.
Save email to the database and send it using a console application triggered as a scheduled task. We like this option because it gives us an archive of sent email. On the other hand we'd need to hit the database to store the emails, which may be slower than asking IIS to dump outgoing mail to a queue folder.
Have IIS save outgoing mail to a queue folder, and write a console application to process that queue. We could archive each message on disk, which is a worse archiving solution than storing in database.
Something else.
Can anyone tell us the most performant solution base on their experience?
Thanks!
Call your email function in a separate thread, that will send emails in background
Try this code.
public static void SendEmail(string from, string[] to, string[] CC, string[] BCC, string subject, string body, SMTPSettings _smtp = null)
{
Thread email = new Thread(delegate()
{
SendAsyncEmail(from, to, CC, BCC, subject, body, _smtp);
});
email.IsBackground = true;
email.Start();
}
private static void SendAsyncEmail(string from, string[] to, string[] CC, string[] BCC, string subject, string body, SMTPSettings _smtp = null)
{
try
{
MailMessage message = new MailMessage();
SmtpClient client = new SmtpClient();
if (_smtp != null)
{
client.Host = _smtp.SMTPServer;
client.Port = Convert.ToInt32(_smtp.SMTPPort);
client.EnableSsl = _smtp.SMTPEnableSSL;
client.Credentials = new System.Net.NetworkCredential(_smtp.SMTPUserEmail, SMTPPassword);
}
message.From = new MailAddress(from);
message.Subject = subject;
message.Body = body;
message.IsBodyHtml = true;
foreach (string t in to)
{
message.To.Add(new MailAddress(t));
}
if (CC != null)
foreach (string c in CC)
{
message.CC.Add(new MailAddress(c));
}
if (BCC != null)
foreach (string b in BCC)
{
message.Bcc.Add(new MailAddress(b));
}
client.Send(message);
}
catch (Exception ex)
{
ErrorLogRepository.LogErrorToDatabase(ex, null, null, "");
}
}
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.