Results 1 to 8 of 8

Thread: [RESOLVED] C# application getting error using SMTP for one user who got a new computer

  1. #1

    Thread Starter
    PowerPoster MMock's Avatar
    Join Date
    Apr 2007
    Location
    My Mustang GT
    Posts
    4,566

    Resolved [RESOLVED] C# application getting error using SMTP for one user who got a new computer

    There is a function in my application where a user creates an Excel file and sends it as an attachment to a group email, let's call it [email protected], using SMTP. A user who has always been able to do this successfully until yesterday is getting this exception. I wrote this block of code yesterday to catch SmtpFailedRecipientsException when I was getting a very general exception "Unable to send to all recipients". This message is not much better. It says Failed Recipient: <[email protected]> Status Code: Mailbox unavailable.

    Code:
                            // 06/22/26 - Code from google search of "c# SmtpClient message unable to send to all recipients".
                            catch (SmtpFailedRecipientsException ex)
                            {
                                // Loops through only the specific recipients that failed
                                foreach (SmtpFailedRecipientException innerEx in ex.InnerExceptions)
                                {
                                    //Console.WriteLine($"Failed recipient: {innerEx.FailedRecipient}");
                                    //Console.WriteLine($"SMTP Status Code: {innerEx.StatusCode}");
                                    MessageBox.Show(String.Format("Failed Recipient: {0} Status Code: {1}", innerEx.FailedRecipient, innerEx.StatusCode));
                                }
                            }
    The mailbox should not be unavailable. Another user sent it fine. So I don't think it's my code, I think it's the user's "new computer". Does anybody know of something that needs to be set up/configured to be able to do this? What about the new computer is relevant: OS, programs installed, etc.? I think I can fix the problem by taking the 5 or so people who are in the group and adding them one at a time to the MailMessage.To list, but that won't really help us know what this problem is and I would like to know that. Thank you for any insight.
    There are 10 kinds of people in this world. Those who understand binary, and those who don't.

  2. #2
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Posts
    12,394

    Re: C# application getting error using SMTP for one user who got a new computer

    There are a few things that this could be. Are you manually setting up credentials or are you using default credentials? Also, does the SMTP server have an IP address whitelist? If so, then the new machine's IP could have changed, and the whitelist simply needs to be updated.

    Bottom line, I doubt that this is a code issue. This appears to be a much more frustrating issue: networking related.
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | HtmlLessons | CssLessons | Code Tags | Sword of Fury - Jameram

  3. #3

    Thread Starter
    PowerPoster MMock's Avatar
    Join Date
    Apr 2007
    Location
    My Mustang GT
    Posts
    4,566

    Re: C# application getting error using SMTP for one user who got a new computer

    Thanks for the reply. Re: credentials, here is the complete code block. I believe if you don't say explicitly, then UseDefaultCredentials is true.

    We will look into whitelist. That came up previously. (By AI, but I trust you more LOL).


    Code:
    using (MailMessage message = new MailMessage())
    {
        using (SmtpClient smtp = new SmtpClient())
        {
            try
            {
                message.From = new MailAddress("[email protected]");  
    
    
                message.To.Add(new MailAddress(Globals.Variables.SpecialHandlingEmail));   // This is the email group of 5 or so peeps
    
                message.CC.Add(new MailAddress(emp.EmailAddress));
    
                message.Subject = emailSubject;
    
                message.IsBodyHtml = true;     // true or false, whether we want to make message body html or plain text
    
                message.Body = emailBody;
    
                if (fileName != "")
                {
                    System.Net.Mail.Attachment attachment;
                    attachment = new System.Net.Mail.Attachment(fileName);
                    message.Attachments.Add(attachment);
                }
    
                smtp.Port = 25;
    
                smtp.Host = "XXX.outlook.com";
    
                smtp.EnableSsl = true;
    
                smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
                smtp.Send(message);
            }
    
            // 06/22/26 - Code from google search of "c# SmtpClient message unable to send to all recipients".
            catch (SmtpFailedRecipientsException ex)
            {
                // Loops through only the specific recipients that failed
                foreach (SmtpFailedRecipientException innerEx in ex.InnerExceptions)
                {
                    //Console.WriteLine($"Failed recipient: {innerEx.FailedRecipient}");
                    //Console.WriteLine($"SMTP Status Code: {innerEx.StatusCode}");
                    MessageBox.Show(String.Format("Failed Recipient: {0} Status Code: {1}", innerEx.FailedRecipient, innerEx.StatusCode));
                }
            }
    
            // 06/22/26 - This was my general error handler that has been here all along.  I added the caption so we know that yes it is CMS giving this error, but really CMS is passing it along from SMTP.
            catch (Exception ex)
            {
                //MessageBox.Show(ex.Message);
                MessageBox.Show(ex.Message, "CMS 2.0 Unknown SMTP Error");
                return false;
            }
        }
    }
    There are 10 kinds of people in this world. Those who understand binary, and those who don't.

  4. #4

    Thread Starter
    PowerPoster MMock's Avatar
    Join Date
    Apr 2007
    Location
    My Mustang GT
    Posts
    4,566

    Re: C# application getting error using SMTP for one user who got a new computer

    Ugh. I just wrote a whole reply and my token had expired so it went poof ?
    So again, this is not an issue anymore. We have a way that remote users are supposed to log in and run my application off a server. Per our network engineer, "Our internal mail connector will only accept messages originating from the office". The user with the problem was using RDP directly and running my app locally. I didn't think to ask, I assumed she was following the rules and concentrated on the "new computer" part of her story. She's all set now and I've learned to ask the obvious up front.
    There are 10 kinds of people in this world. Those who understand binary, and those who don't.

  5. #5
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Posts
    12,394

    Re: [RESOLVED] C# application getting error using SMTP for one user who got a new com

    Are you using an older version of the Outlook SMTP? The reason I ask is because I'm not familiar with port 25, typically it's port 587. Take a look at this table (SMTP is towards the bottom): https://support.microsoft.com/en-us/...or-outlook-com

    You're already turning on EnableSsl, which is correct. However, the way I've done it in the past is to use port 587.

    By the way, you could pass many of the variables in the various class constructors to save on some lines of code, though this is a style preference. Also, I'd probably recommend implementing an interface for this. You might not need it now, but it greatly simplifies the process if you ever needed to switch from Outlook to something else.

    Try this for instance (untested, but should give you an idea):
    Code:
    public interface ISmtpEmailer
    {
    	public int Port { get; }
    	public string Server { get; }
    	
    	public Task SendAsync(string subject, string body, string attachment, string emailFrom, string emailTo);
    	public Task SendAsync(string subject, string body, string attachment, string emailFrom, string emailTo, string emailCC);
    	public Task SendAsync(string subject, string body, string attachment, string emailFrom, string emailTo, string emailCC, string emailBCC);
    	public Task SendAsync(string subject, string body, string attachment, string emailFrom, IEnumerable<string> emailsTo);
    	public Task SendAsync(string subject, string body, string attachment, string emailFrom, IEnumerable<string> emailsTo, IEnumerable<string> emailsCC);
    	public Task SendAsync(string subject, string body, string attachment, string emailFrom, IEnumerable<string> emailsTo, IEnumerable<string> emailsCC, IEnumerable<string> emailsBCC);
    }
    
    public class OutlookEmailer : ISmtpEmailer
    {
    	
    	public int Port { get => 587; }
    	public string Server { get => "smtp.outlook.com"; }
    	
    	public async Task SendAsync(string subject, string body, string attachment, string emailFrom, string emailTo)
    	{
    		await SendAsync(subject, body, attachment, emailFrom, [ emailTo ]);
    	}
    	
    	public async Task SendAsync(string subject, string body, string attachment, string emailFrom, string emailTo, string emailCC)
    	{
    		await SendAsync(subject, body, attachment, emailFrom, [ emailTo ], [ emailCC ]);
    	}
    	
    	public async Task SendAsync(string subject, string body, string attachment, string emailFrom, string emailTo, string emailCC, string emailBCC)
    	{
    		await SendAsync(subject, body, attachment, emailFrom, [ emailTo ], [ emailCC ], [ emailBCC ]);
    	}
    	
    	public async Task SendAsync(string subject, string body, string attachment, string emailFrom, IEnumerable<string> emailsTo)
    	{
    		await SendAsync(subject, body, attachment, emailFrom, emailsTo, []);
    	}
    	
    	public async Task SendAsync(string subject, string body, string attachment, string emailFrom, IEnumerable<string> emailsTo, IEnumerable<string> emailsCC)
    	{
    		await SendAsync(subject, body, attachment, emailFrom, emailsTo, emailsCC, []);
    	}
    	
    	public async Task SendAsync(string subject, string body, string attachment, string emailFrom, IEnumerable<string> emailsTo, IEnumerable<string> emailsCC, IEnumerable<string> emailsBCC)
    	{
    		// require subject
    		if (string.IsNullOrWhiteSpace(subject))
    		{
    			throw new ArgumentOutOfRangeException(nameof(subject));
    		}
    		
    		// require body
    		if (string.IsNullOrWhiteSpace(body))
    		{
    			throw new ArgumentOutOfRangeException(nameof(body));
    		}
    		
    		// require email from
    		if (string.IsNullOrWhiteSpace(emailFrom))
    		{
    			throw new ArgumentOutOfRangeException(nameof(emailFrom));
    		}
    
    		// require email to
    		if (!emailsTo.Any())
    		{
    			throw new ArgumentOutOfRangeException(nameof(emailsTo), $"{nameof(emailsTo)} cannot be empty.");
    		}
    		ParseEmailAddresses(emailsTo);
    		var mailAddressesTo = string.Join(",", emailsTo);
    
    		using (MailMessage message = new MailMessage(emailFrom, mailAddressesTo, subject, body))
    		using (SmtpClient smtp = new SmtpClient(Server, Port))
    		{
    			// get any optional CCs
    			if (emailsCC.Any())
    			{
    				var parsedCCEmails = ParseEmailAddresses(emailsCC);
    				foreach (var parsedEmail in parsedCCEmails)
    				{
    					message.CC.Add(parsedEmail);
    				}
    			}
    
    			// get any optional BCCs
    			if (emailsBCC.Any())
    			{
    				var parsedBCCEmails = ParseEmailAddresses(emailsBCC);
    				foreach (var parsedEmail in parsedBCCEmails)
    				{
    					message.Bcc.Add(parsedEmail);
    				}
    			}
    			
    			// set remaining email options
    			message.IsBodyHtml = true;
    			if (!string.IsNullOrWhiteSpace(attachment))
    			{
    				var emailAttachment = new Attachment(attachment);
    				message.Attachments.Add(emailAttachment);
    			}
    			
    			// set SMTP options
    			smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
    			smtp.EnableSsl = true;
    			smtp.UseDefaultCredentials = true;
    			
    			// send baby, send!
    			await smtp.SendMailAsync(message);
    		}
    	}
    	
    	private static MailAddressCollection ParseEmailAddresses(IEnumerable<string> emailAddresses)
    	{
    		var emailCollection = new MailAddressCollection();
    		var invalidEmails = new List<string>();
    		foreach (var email in emailAddresses)
    		{
    			if (!MailAddress.TryCreate(email, out var parsedMailAddress))
    			{
    				invalidEmails.Add(email);
    			}
    			else
    			{
    				emailCollection.Add(parsedMailAddress);
    			}
    		}
    		if (invalidEmails.Any())
    		{
    			var joinedEmails = string.Join(", ", invalidEmails);
    			throw new FormatException($"The following email addresses are invalid: {joinedEmails}");
    		}
    		
    		return emailCollection;
    	}
    	
    }
    Unusable Demo (because of limitations): https://dotnetfiddle.net/5RSRpc
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | HtmlLessons | CssLessons | Code Tags | Sword of Fury - Jameram

  6. #6
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Posts
    12,394

    Re: C# application getting error using SMTP for one user who got a new computer

    Quote Originally Posted by MMock View Post
    I didn't think to ask, I assumed she was following the rules and concentrated on the "new computer" part of her story. She's all set now and I've learned to ask the obvious up front.
    Oh man, it's even worse than a networking issue. It's a human issue!!!
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | HtmlLessons | CssLessons | Code Tags | Sword of Fury - Jameram

  7. #7

    Thread Starter
    PowerPoster MMock's Avatar
    Join Date
    Apr 2007
    Location
    My Mustang GT
    Posts
    4,566

    Re: [RESOLVED] C# application getting error using SMTP for one user who got a new com

    OK, the 587 vs 25 difference is interesting. Because when I was originally developing this 5 years ago, I didn't right away have the info needed to work with our internal outlook mail server. So to keep going, I temporarily used a gmail account. (I don't remember this all very well but knowing that I don't remember, I made a lot of notes!) When it was gmail, I used Port = 587 and Host = "smtp.gmail.com". But then I guess our engineer told me to use Port 25 and what our host name was. And it's been that way since.
    There are 10 kinds of people in this world. Those who understand binary, and those who don't.

  8. #8
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Posts
    12,394

    Re: [RESOLVED] C# application getting error using SMTP for one user who got a new com

    Based on what you're describing, it sounds like you're actually using SMTP Relay. Check out this documentation: https://learn.microsoft.com/en-us/ex...-or-office-365

    The reason for this guess is because it uses port 25 and requires one or more static IP addresses to be authenticated based on the "Our internal mail connector will only accept messages originating from the office" quote.
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | HtmlLessons | CssLessons | Code Tags | Sword of Fury - Jameram

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width